From deea3cae8e848388ee962a92de58dc42b77915d1 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Sat, 22 Aug 2026 21:02:05 +0200 Subject: Store MUC features only in EntityInfo (not in MucFlag), update on change --- xmpp-vala/src/module/xep/0045_muc/flag.vala | 17 ------ xmpp-vala/src/module/xep/0045_muc/module.vala | 71 +++------------------- .../src/module/xep/0115_entity_capabilities.vala | 5 -- 3 files changed, 8 insertions(+), 85 deletions(-) (limited to 'xmpp-vala/src/module') diff --git a/xmpp-vala/src/module/xep/0045_muc/flag.vala b/xmpp-vala/src/module/xep/0045_muc/flag.vala index d0d2c359..a72965b3 100644 --- a/xmpp-vala/src/module/xep/0045_muc/flag.vala +++ b/xmpp-vala/src/module/xep/0045_muc/flag.vala @@ -5,9 +5,6 @@ namespace Xmpp.Xep.Muc { public class Flag : XmppStreamFlag { public static FlagIdentity IDENTITY = new FlagIdentity(NS_URI, "muc"); - private HashMap> room_features = new HashMap>(Jid.hash_bare_func, Jid.equals_bare_func); - private HashMap room_names = new HashMap(Jid.hash_bare_func, Jid.equals_bare_func); - private HashMap enter_ids = new HashMap(Jid.hash_bare_func, Jid.equals_bare_func); public HashMap> enter_futures = new HashMap>(Jid.hash_func, Jid.equals_func); private HashMap own_nicks = new HashMap(Jid.hash_bare_func, Jid.equals_bare_func); @@ -18,12 +15,6 @@ public class Flag : XmppStreamFlag { private HashMap> affiliations = new HashMap>(Jid.hash_bare_func, Jid.equals_bare_func); private HashMap occupant_role = new HashMap(Jid.hash_func, Jid.equals_func); - public string? get_room_name(Jid muc_jid) { return room_names.has_key(muc_jid.bare_jid) ? room_names[muc_jid.bare_jid] : null; } - - public bool has_room_feature(Jid muc_jid, Feature feature) { - return room_features.has_key(muc_jid.bare_jid) && room_features[muc_jid.bare_jid].contains(feature); - } - public Jid? get_real_jid(Jid full_jid) { return occupant_real_jids[full_jid]; } public Jid? get_occupant_jid(Jid real_jid, Jid room) { @@ -77,14 +68,6 @@ public class Flag : XmppStreamFlag { public string? get_muc_subject(Jid muc_jid) { return subjects[muc_jid.bare_jid]; } - internal void set_room_name(Jid muc_jid, string name) { - room_names[muc_jid.bare_jid] = name; - } - - internal void set_room_features(Jid muc_jid, Gee.List features) { - room_features[muc_jid.bare_jid] = features; - } - internal void set_real_jid(Jid full_jid, Jid real_jid) { occupant_real_jids[full_jid] = real_jid; } internal void set_offline_member(Jid muc_jid, Jid real_jid, Affiliation affiliation) { diff --git a/xmpp-vala/src/module/xep/0045_muc/module.vala b/xmpp-vala/src/module/xep/0045_muc/module.vala index ad929b00..76045172 100644 --- a/xmpp-vala/src/module/xep/0045_muc/module.vala +++ b/xmpp-vala/src/module/xep/0045_muc/module.vala @@ -8,6 +8,12 @@ private const string NS_URI_OWNER = NS_URI + "#owner"; public const string NS_URI_USER = NS_URI + "#user"; private const string NS_URI_REQUEST = NS_URI + "#request"; +public const string FEATURE_STABLE_ID = "http://jabber.org/protocol/muc#stable_id"; +public const string FEATURE_MEMBERS_ONLY = "muc_membersonly"; +public const string FEATURE_MODERATED = "muc_moderated"; +public const string FEATURE_NON_ANONYMOUS = "muc_nonanonymous"; +public const string FEATURE_PASSWORD_PROTECTED = "muc_passwordprotected"; + public enum MucEnterError { PASSWORD_REQUIRED, BANNED, @@ -34,26 +40,6 @@ public enum Role { VISITOR } -public enum Feature { - REGISTER, - ROOMCONFIG, - ROOMINFO, - HIDDEN, - MEMBERS_ONLY, - MODERATED, - NON_ANONYMOUS, - OPEN, - PASSWORD_PROTECTED, - PERSISTENT, - PUBLIC, - ROOMS, - SEMI_ANONYMOUS, - STABLE_ID, - TEMPORARY, - UNMODERATED, - UNSECURED -} - public static void add_muc_pm_message_stanza_x_node(MessageStanza message_stanza) { StanzaNode x_node = new StanzaNode.build("x", "http://jabber.org/protocol/muc#user").add_self_xmlns(); message_stanza.stanza.put_node(x_node); @@ -74,6 +60,7 @@ public class Module : XmppStreamModule { public signal void subject_set(XmppStream stream, string? subject, Jid jid); public signal void invite_received(XmppStream stream, Jid room_jid, Jid from_jid, string? password, string? reason); public signal void voice_request_received(XmppStream stream, Jid room_jid, Jid from_jid, string nick); + public signal void room_info_changed(XmppStream stream, Jid muc_jid); public signal void room_info_updated(XmppStream stream, Jid muc_jid); public signal void self_removed_from_room(XmppStream stream, Jid jid, StatusCode code); @@ -299,7 +286,7 @@ public class Module : XmppStreamModule { if (status_codes.contains(StatusCode.CONFIG_CHANGE_NON_PRIVACY) || status_codes.contains(StatusCode.NON_ANONYMOUS) || status_codes.contains(StatusCode.SEMI_ANONYMOUS)) { - query_room_info.begin(stream, message.from.bare_jid); + room_info_changed(stream, message.from.bare_jid); } } } @@ -358,9 +345,6 @@ public class Module : XmppStreamModule { if (status_codes.contains(StatusCode.SELF_PRESENCE)) { Jid bare_jid = presence.from.bare_jid; if (flag.get_enter_id(bare_jid) != null) { - - query_room_info.begin(stream, bare_jid); - flag.finish_muc_enter(bare_jid); var join_result = new JoinResult() { nick=presence.from.resourcepart, newly_created=status_codes.contains(StatusCode.NEW_ROOM_CREATED) }; flag.enter_futures[bare_jid].set_value(join_result); @@ -430,45 +414,6 @@ public class Module : XmppStreamModule { } } - private async void query_room_info(XmppStream stream, Jid jid) { - ServiceDiscovery.InfoResult? info_result = yield stream.get_module(ServiceDiscovery.Module.IDENTITY).request_info(stream, jid); - if (info_result == null) return; - - Gee.List features = new ArrayList(); - - foreach (ServiceDiscovery.Identity identity in info_result.identities) { - if (identity.category == "conference" && identity.name != null) { - stream.get_flag(Flag.IDENTITY).set_room_name(jid, identity.name); - } - } - - foreach (string feature in info_result.features) { - Feature? parsed = null; - switch (feature) { - case "http://jabber.org/protocol/muc#register": parsed = Feature.REGISTER; break; - case "http://jabber.org/protocol/muc#roomconfig": parsed = Feature.ROOMCONFIG; break; - case "http://jabber.org/protocol/muc#roominfo": parsed = Feature.ROOMINFO; break; - case "http://jabber.org/protocol/muc#stable_id": parsed = Feature.STABLE_ID; break; - case "muc_hidden": parsed = Feature.HIDDEN; break; - case "muc_membersonly": parsed = Feature.MEMBERS_ONLY; break; - case "muc_moderated": parsed = Feature.MODERATED; break; - case "muc_nonanonymous": parsed = Feature.NON_ANONYMOUS; break; - case "muc_open": parsed = Feature.OPEN; break; - case "muc_passwordprotected": parsed = Feature.PASSWORD_PROTECTED; break; - case "muc_persistent": parsed = Feature.PERSISTENT; break; - case "muc_public": parsed = Feature.PUBLIC; break; - case "muc_rooms": parsed = Feature.ROOMS; break; - case "muc_semianonymous": parsed = Feature.SEMI_ANONYMOUS; break; - case "muc_temporary": parsed = Feature.TEMPORARY; break; - case "muc_unmoderated": parsed = Feature.UNMODERATED; break; - case "muc_unsecured": parsed = Feature.UNSECURED; break; - } - if (parsed != null) features.add(parsed); - } - stream.get_flag(Flag.IDENTITY).set_room_features(jid, features); - room_info_updated(stream, jid); - } - public async void fetch_affiliations(XmppStream stream, Jid muc_jid) { query_affiliation.begin(stream, muc_jid, "member"); query_affiliation.begin(stream, muc_jid, "admin"); diff --git a/xmpp-vala/src/module/xep/0115_entity_capabilities.vala b/xmpp-vala/src/module/xep/0115_entity_capabilities.vala index 8e15e0c2..e39dcbbd 100644 --- a/xmpp-vala/src/module/xep/0115_entity_capabilities.vala +++ b/xmpp-vala/src/module/xep/0115_entity_capabilities.vala @@ -35,11 +35,6 @@ namespace Xmpp.Xep.EntityCapabilities { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0115_entity_capabilities"); private string own_ver_hash; - private Storage storage; - - public Module(Storage storage) { - this.storage = storage; - } private string get_own_hash(XmppStream stream) { if (own_ver_hash == null) { -- cgit v1.3 From cd0d992b9b5d3ea29c7d4a3aab76ad53319ea162 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sat, 3 Oct 2026 13:22:02 +0200 Subject: Move ICE into libdino --- libdino/meson.build | 2 + libdino/src/service/ice.vala | 538 +++++++++++++++++++++ libdino/src/service/module_manager.vala | 5 +- libdino/src/service/util.vala | 12 +- libdino/vapi/metadata/Nice-0.1.metadata | 11 + libdino/vapi/nice.vapi | 386 +++++++++++++++ plugins/ice/meson.build | 25 - plugins/ice/src/module.vala | 57 --- plugins/ice/src/plugin.vala | 104 ---- plugins/ice/src/register_plugin.vala | 3 - plugins/ice/src/transport_parameters.vala | 391 --------------- plugins/ice/src/util.vala | 18 - plugins/ice/vapi/metadata/Nice-0.1.metadata | 11 - plugins/ice/vapi/nice.vapi | 386 --------------- plugins/meson.build | 1 - .../src/module/xep/0065_socks5_bytestreams.vala | 4 + xmpp-vala/src/module/xep/0177_jingle_raw_udp.vala | 4 + 17 files changed, 956 insertions(+), 1002 deletions(-) create mode 100644 libdino/src/service/ice.vala create mode 100644 libdino/vapi/metadata/Nice-0.1.metadata create mode 100644 libdino/vapi/nice.vapi delete mode 100644 plugins/ice/meson.build delete mode 100644 plugins/ice/src/module.vala delete mode 100644 plugins/ice/src/plugin.vala delete mode 100644 plugins/ice/src/register_plugin.vala delete mode 100644 plugins/ice/src/transport_parameters.vala delete mode 100644 plugins/ice/src/util.vala delete mode 100644 plugins/ice/vapi/metadata/Nice-0.1.metadata delete mode 100644 plugins/ice/vapi/nice.vapi (limited to 'xmpp-vala/src/module') diff --git a/libdino/meson.build b/libdino/meson.build index 67ac6a83..e680b662 100644 --- a/libdino/meson.build +++ b/libdino/meson.build @@ -9,6 +9,7 @@ dependencies = [ dep_gmodule, dep_libsoup, dep_libsrtp2, + dep_nice, dep_sqlite3, dep_xmpp_vala ] @@ -63,6 +64,7 @@ sources = files( 'src/service/file_manager.vala', 'src/service/file_transfer_storage.vala', 'src/service/history_sync.vala', + 'src/service/ice.vala', 'src/service/jingle_file_transfers.vala', 'src/service/message_correction.vala', 'src/service/message_deletion.vala', diff --git a/libdino/src/service/ice.vala b/libdino/src/service/ice.vala new file mode 100644 index 00000000..0e168be9 --- /dev/null +++ b/libdino/src/service/ice.vala @@ -0,0 +1,538 @@ +using Gee; + +using Dino.Crypto; +using Xmpp; +using Xmpp.Xep; + +private extern const size_t NICE_ADDRESS_STRING_LEN; + +public class Dino.IceUdpModule : Xmpp.Xep.JingleIceUdp.Module { + + public string? stun_ip = null; + public uint stun_port = 0; + public string? turn_ip = null; + public Xep.ExternalServiceDiscovery.Service? turn_service = null; + + private static weak Nice.Agent? agent; + private HashMap cerds = new HashMap(); + + private uint timeout = 0; + + public override void attach(XmppStream stream) { + base.attach(stream); + external_discovery_refresh_services.begin(stream); + } + public override void detach(XmppStream stream) { + base.detach(stream); + stop_external_discovery_refresh_services(); + } + + private Nice.Agent get_agent() { + Nice.Agent? agent = this.agent; + if (agent == null) { + Nice.debug_enable(true); + agent = new Nice.Agent(MainContext.@default(), Nice.Compatibility.RFC5245); + if (stun_ip != null) { + agent.stun_server = stun_ip; + agent.stun_server_port = stun_port; + } + agent.ice_tcp = false; + agent.set_software("Dino"); + agent.weak_ref(agent_unweak); + this.agent = agent; + debug("STUN server for libnice %s %u", agent.stun_server, agent.stun_server_port); + } + return agent; + } + + private void agent_unweak() { + this.agent = null; + } + + public override Jingle.TransportParameters create_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid) { + DtlsSrtp.CredentialsCapsule? cred = get_create_credentials(local_full_jid, peer_full_jid); + return new IceUdpTransportParameters(get_agent(), cred, turn_service, turn_ip, components, local_full_jid, peer_full_jid); + } + + public override Jingle.TransportParameters parse_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid, StanzaNode transport) throws Jingle.IqError { + DtlsSrtp.CredentialsCapsule? cred = get_create_credentials(local_full_jid, peer_full_jid); + return new IceUdpTransportParameters(get_agent(), cred, turn_service, turn_ip, components, local_full_jid, peer_full_jid, transport); + } + + private DtlsSrtp.CredentialsCapsule? get_create_credentials(Jid local_full_jid, Jid peer_full_jid) { + string from_to_id = local_full_jid.to_string() + peer_full_jid.to_string(); + try { + if (!cerds.has_key(from_to_id)) cerds[from_to_id] = DtlsSrtp.generate_credentials(); + } catch (GLib.Error e) { + warning("Error creating dtls credentials: %s", e.message); + } + return cerds[from_to_id]; + } + + private void stop_external_discovery_refresh_services() { + if (timeout != 0) { + Source.remove(timeout); + timeout = 0; + } + } + + private async void external_discovery_refresh_services(XmppStream stream) { + stop_external_discovery_refresh_services(); + Gee.List 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 (ip.is_any || ip.is_link_local || ip.is_loopback || ip.is_multicast || ip.is_site_local) { + warning("Ignoring STUN/TURN server at %s", service.host); + continue; + } + + if (service.ty == "stun") { + debug("Server offers STUN server: %s:%u, resolved to %s", service.host, service.port, ip.to_string()); + stun_ip = ip.to_string(); + 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()); + turn_ip = ip.to_string(); + turn_service = service; + } + } + } + if (stun_ip == null) { + InetAddress ip = yield lookup_ipv4_addess("stun.dino.im"); + if (ip == null) return; + + debug("Using fallback STUN server: stun.dino.im:7886, resolved to %s", ip.to_string()); + + stun_ip = ip.to_string(); + stun_port = 7886; + } + + // Refresh TURN credentials before they expire + if (turn_service != null) { + DateTime? expires = turn_service.expires; + if (expires != null) { + uint refresh_delay = (uint) (expires.to_unix() - new DateTime.now_utc().to_unix()) / 2; + + if (refresh_delay >= 300 && refresh_delay <= (int64) uint.MAX) { // 5 min < refetch < max + debug("Re-fetching TURN credentials in %u sec", refresh_delay); + + stop_external_discovery_refresh_services(); + timeout = Timeout.add_seconds((uint) refresh_delay, () => { + timeout = 0; + external_discovery_refresh_services.begin(stream); + return false; + }); + } else { + warning("TURN credentials' expiry time = %u, *not* re-fetching", refresh_delay); + } + } + } + } + + private async InetAddress? lookup_ipv4_addess(string host) { + try { + Resolver resolver = Resolver.get_default(); + GLib.List? ips = yield resolver.lookup_by_name_async(host); + foreach (GLib.InetAddress ina in ips) { + if (ina.get_family() != SocketFamily.IPV4) continue; + return ina; + } + } catch (GLib.Error e) { + warning("Failed looking up IP address of %s", host); + } + return null; + } +} + +public class Dino.IceUdpTransportParameters : JingleIceUdp.IceUdpTransportParameters { + private Nice.Agent agent; + private uint stream_id; + private bool we_want_connection; + private bool remote_credentials_set; + private Map connections = new HashMap(); + private DtlsSrtp.Handler? dtls_srtp_handler; + private MainContext thread_context; + private MainLoop thread_loop; + + private static bool is_component_ready(Nice.Agent agent, uint stream_id, uint component_id) { + var state = agent.get_component_state(stream_id, component_id); + return state == Nice.ComponentState.CONNECTED || state == Nice.ComponentState.READY; + } + + private class DatagramConnection : Jingle.DatagramConnection { + private Nice.Agent agent; + private DtlsSrtp.Handler? dtls_srtp_handler; + private uint stream_id; + private string? error; + private ulong datagram_received_id; + + internal DatagramConnection(Nice.Agent agent, DtlsSrtp.Handler? dtls_srtp_handler, uint stream_id, uint8 component_id) { + this.agent = agent; + this.dtls_srtp_handler = dtls_srtp_handler; + this.stream_id = stream_id; + this.component_id = component_id; + this.datagram_received_id = this.datagram_received.connect((datagram) => { + bytes_received += datagram.length; + }); + } + + public override async void terminate(bool we_terminated, string? reason_string = null, string? reason_text = null) { + yield base.terminate(we_terminated, reason_string, reason_text); + this.disconnect(datagram_received_id); + agent = null; + dtls_srtp_handler = null; + } + + public override void send_datagram(Bytes datagram) { + if (this.agent != null && is_component_ready(agent, stream_id, component_id)) { + try { + if (dtls_srtp_handler != null) { + uint8[] encrypted_data = dtls_srtp_handler.process_outgoing_data(component_id, datagram.get_data()); + if (encrypted_data == null) return; + GLib.OutputVector vector = { encrypted_data, encrypted_data.length }; + GLib.OutputVector[] vectors = { vector }; + Nice.OutputMessage message = { vectors }; + Nice.OutputMessage[] messages = { message }; + agent.send_messages_nonblocking(stream_id, component_id, messages); + } else { + GLib.OutputVector vector = { datagram.get_data(), datagram.get_size() }; + GLib.OutputVector[] vectors = { vector }; + Nice.OutputMessage message = { vectors }; + Nice.OutputMessage[] messages = { message }; + agent.send_messages_nonblocking(stream_id, component_id, messages); + } + bytes_sent += datagram.length; + } catch (GLib.Error e) { + warning("%s while send_datagram stream %u component %u", e.message, stream_id, component_id); + } + } + } + } + + internal IceUdpTransportParameters(Nice.Agent agent, DtlsSrtp.CredentialsCapsule? credentials, Xep.ExternalServiceDiscovery.Service? turn_service, string? turn_ip, uint8 components, Jid local_full_jid, Jid peer_full_jid, StanzaNode? node = null) { + base(components, local_full_jid, peer_full_jid, node); + this.we_want_connection = (node == null); + this.agent = agent; + + if (this.peer_fingerprint != null || !incoming) { + dtls_srtp_handler = setup_dtls(this, credentials); + own_fingerprint = dtls_srtp_handler.own_fingerprint; + if (incoming) { + own_setup = "active"; + dtls_srtp_handler.mode = DtlsSrtp.Mode.CLIENT; + dtls_srtp_handler.peer_fingerprint = peer_fingerprint; + dtls_srtp_handler.peer_fp_algo = peer_fp_algo; + } else { + own_setup = "actpass"; + dtls_srtp_handler.mode = DtlsSrtp.Mode.SERVER; + dtls_srtp_handler.setup_dtls_connection.begin((_, res) => { + var content_encryption = dtls_srtp_handler.setup_dtls_connection.end(res); + if (content_encryption != null) { + this.content.encryptions[content_encryption.encryption_ns] = content_encryption; + } + }); + } + } + + agent.candidate_gathering_done.connect(on_candidate_gathering_done); + agent.initial_binding_request_received.connect(on_initial_binding_request_received); + agent.component_state_changed.connect(on_component_state_changed); + agent.new_selected_pair_full.connect(on_new_selected_pair_full); + agent.new_candidate_full.connect(on_new_candidate); + + agent.controlling_mode = !incoming; + stream_id = agent.add_stream(components); + thread_context = new MainContext(); + new Thread(@"ice-thread-$stream_id", () => { + thread_context.push_thread_default(); + thread_loop = new MainLoop(thread_context, false); + thread_loop.run(); + thread_context.pop_thread_default(); + return null; + }); + + if (turn_ip != null) { + for (uint8 component_id = 1; component_id <= components; component_id++) { + agent.set_relay_info(stream_id, component_id, turn_ip, turn_service.port, turn_service.username, turn_service.password, Nice.RelayType.UDP); + debug("TURN info (component %i) %s:%u", component_id, turn_ip, turn_service.port); + } + } + string ufrag; + string pwd; + agent.get_local_credentials(stream_id, out ufrag, out pwd); + init(ufrag, pwd); + + for (uint8 component_id = 1; component_id <= components; component_id++) { + // We don't properly get local candidates before this call + agent.attach_recv(stream_id, component_id, thread_context, on_recv); + } + + agent.gather_candidates(stream_id); + } + + private static DtlsSrtp.Handler setup_dtls(IceUdpTransportParameters tp, DtlsSrtp.CredentialsCapsule credentials) { + var weak_self = WeakRef(tp); + DtlsSrtp.Handler dtls_srtp = new DtlsSrtp.Handler.with_cert(credentials); + dtls_srtp.send_data.connect((data) => { + IceUdpTransportParameters self = (IceUdpTransportParameters) weak_self.get(); + if (self != null) self.agent.send(self.stream_id, 1, data); + }); + return dtls_srtp; + } + + private void on_candidate_gathering_done(uint stream_id) { + if (stream_id != this.stream_id) return; + debug("on_candidate_gathering_done in %u", stream_id); + + for (uint8 i = 1; i <= components; i++) { + foreach (unowned Nice.Candidate nc in agent.get_local_candidates(stream_id, i)) { + if (nc.transport == Nice.CandidateTransport.UDP) { + JingleIceUdp.Candidate? candidate = candidate_to_jingle(nc); + if (candidate == null) continue; + debug("Local candidate summary: %s", agent.generate_local_candidate_sdp(nc)); + } + } + } + } + + private void on_new_candidate(Nice.Candidate nc) { + if (nc.stream_id != stream_id) return; + JingleIceUdp.Candidate? candidate = candidate_to_jingle(nc); + if (candidate == null) return; + + if (nc.transport == Nice.CandidateTransport.UDP) { + // Execution was in the agent thread before + add_local_candidate_threadsafe(candidate); + } + } + + private bool bytes_equal(uint8[] a1, uint8[] a2) { + return a1.length == a2.length && Memory.cmp(a1, a2, a1.length) == 0; + } + + public override void handle_transport_accept(StanzaNode transport) throws Jingle.IqError { + debug("on_transport_accept from %s", peer_full_jid.to_string()); + base.handle_transport_accept(transport); + + if (dtls_srtp_handler != null && peer_fingerprint != null) { + if (dtls_srtp_handler.peer_fingerprint != null) { + if (!bytes_equal(dtls_srtp_handler.peer_fingerprint, peer_fingerprint)) { + warning("Tried to replace certificate fingerprint mid use. We don't allow that."); + peer_fingerprint = dtls_srtp_handler.peer_fingerprint; + peer_fp_algo = dtls_srtp_handler.peer_fp_algo; + } + } else { + dtls_srtp_handler.peer_fingerprint = peer_fingerprint; + dtls_srtp_handler.peer_fp_algo = peer_fp_algo; + } + if (peer_setup == "passive") { + dtls_srtp_handler.mode = DtlsSrtp.Mode.CLIENT; + dtls_srtp_handler.stop_dtls_connection(); + dtls_srtp_handler.setup_dtls_connection.begin((_, res) => { + var content_encryption = dtls_srtp_handler.setup_dtls_connection.end(res); + if (content_encryption != null) { + this.content.encryptions[content_encryption.encryption_ns] = content_encryption; + } + }); + } + } else { + dtls_srtp_handler = null; + } + } + + public override void handle_transport_info(StanzaNode transport) throws Jingle.IqError { + debug("on_transport_info from %s", peer_full_jid.to_string()); + base.handle_transport_info(transport); + + if (dtls_srtp_handler != null && peer_fingerprint != null) { + if (dtls_srtp_handler.peer_fingerprint != null) { + if (!bytes_equal(dtls_srtp_handler.peer_fingerprint, peer_fingerprint)) { + warning("Tried to replace certificate fingerprint mid use. We don't allow that."); + peer_fingerprint = dtls_srtp_handler.peer_fingerprint; + peer_fp_algo = dtls_srtp_handler.peer_fp_algo; + } + } else { + dtls_srtp_handler.peer_fingerprint = peer_fingerprint; + dtls_srtp_handler.peer_fp_algo = peer_fp_algo; + } + } + + if (!we_want_connection) return; + + if (remote_ufrag != null && remote_pwd != null && !remote_credentials_set) { + agent.set_remote_credentials(stream_id, remote_ufrag, remote_pwd); + remote_credentials_set = true; + } + for (uint8 i = 1; i <= components; i++) { + SList candidates = new SList(); + foreach (JingleIceUdp.Candidate candidate in remote_candidates) { + if (candidate.component == i) { + candidates.append(candidate_to_nice(candidate)); + } + } + int new_candidates = agent.set_remote_candidates(stream_id, i, candidates); + debug("Updated to %i remote candidates for candidate %u via transport info", new_candidates, i); + } + } + + public override void create_transport_connection(XmppStream stream, Jingle.Content content) { + debug("create_transport_connection: %s", content.session.sid); + debug("local_credentials: %s %s", local_ufrag, local_pwd); + debug("remote_credentials: %s %s", remote_ufrag, remote_pwd); + debug("expected incoming credentials: %s %s", local_ufrag + ":" + remote_ufrag, local_pwd); + debug("expected outgoing credentials: %s %s", remote_ufrag + ":" + local_ufrag, remote_pwd); + + we_want_connection = true; + + if (remote_ufrag != null && remote_pwd != null && !remote_credentials_set) { + agent.set_remote_credentials(stream_id, remote_ufrag, remote_pwd); + remote_credentials_set = true; + } + for (uint8 i = 1; i <= components; i++) { + SList candidates = new SList(); + foreach (JingleIceUdp.Candidate candidate in remote_candidates) { + if (candidate.ip.has_prefix("fe80::")) continue; + if (candidate.component == i) { + candidates.append(candidate_to_nice(candidate)); + debug("remote candidate: %s", agent.generate_local_candidate_sdp(candidate_to_nice(candidate))); + } + } + int new_candidates = agent.set_remote_candidates(stream_id, i, candidates); + debug("Initiated component %u with %i remote candidates", i, new_candidates); + + connections[i] = new DatagramConnection(agent, dtls_srtp_handler, stream_id, i); + content.set_transport_connection(connections[i], i); + } + + base.create_transport_connection(stream, content); + } + + private void on_component_state_changed(uint stream_id, uint component_id, uint state) { + if (stream_id != this.stream_id) return; + debug("stream %u component %u state changed to %s", stream_id, component_id, agent.get_component_state(stream_id, component_id).to_string()); + may_consider_ready(stream_id, component_id); + if (incoming && dtls_srtp_handler != null && !dtls_srtp_handler.ready && is_component_ready(agent, stream_id, component_id) && dtls_srtp_handler.mode == DtlsSrtp.Mode.CLIENT) { + dtls_srtp_handler.setup_dtls_connection.begin((_, res) => { + Jingle.ContentEncryption? encryption = dtls_srtp_handler.setup_dtls_connection.end(res); + if (encryption != null) { + this.content.encryptions[encryption.encryption_ns] = encryption; + } + }); + } + } + + private void may_consider_ready(uint stream_id, uint component_id) { + if (stream_id != this.stream_id) return; + if (connections.has_key((uint8) component_id) && !connections[(uint8)component_id].ready && is_component_ready(agent, stream_id, component_id) && (dtls_srtp_handler == null || dtls_srtp_handler.ready)) { + connections[(uint8)component_id].ready = true; + } + } + + private void on_initial_binding_request_received(uint stream_id) { + if (stream_id != this.stream_id) return; + debug("initial_binding_request_received"); + } + + private void on_new_selected_pair_full(uint stream_id, uint component_id, Nice.Candidate p1, Nice.Candidate p2) { + if (stream_id != this.stream_id) return; + debug("new_selected_pair_full %u [%s, %s]", component_id, agent.generate_local_candidate_sdp(p1), agent.generate_local_candidate_sdp(p2)); + } + + private void on_recv(Nice.Agent agent, uint stream_id, uint component_id, uint8[] data) { + if (stream_id != this.stream_id) return; + uint8[] decrypt_data = null; + if (dtls_srtp_handler != null) { + try { + decrypt_data = dtls_srtp_handler.process_incoming_data(component_id, data); + if (decrypt_data == null) return; + } catch (Crypto.Error e) { + warning("%s while on_recv stream %u component %u", e.message, stream_id, component_id); + return; + } + } + may_consider_ready(stream_id, component_id); + if (connections.has_key((uint8) component_id)) { + if (!connections[(uint8) component_id].ready) { + debug("on_recv stream %u component %u when state %s", stream_id, component_id, agent.get_component_state(stream_id, component_id).to_string()); + } + connections[(uint8) component_id].datagram_received(new Bytes(decrypt_data ?? data)); + } else { + debug("on_recv stream %u component %u length %u", stream_id, component_id, data.length); + } + } + + private static Nice.Candidate candidate_to_nice(JingleIceUdp.Candidate c) { + Nice.CandidateType type; + switch (c.type_) { + case JingleIceUdp.Candidate.Type.HOST: type = Nice.CandidateType.HOST; break; + case JingleIceUdp.Candidate.Type.PRFLX: type = Nice.CandidateType.PEER_REFLEXIVE; break; + case JingleIceUdp.Candidate.Type.RELAY: type = Nice.CandidateType.RELAYED; break; + case JingleIceUdp.Candidate.Type.SRFLX: type = Nice.CandidateType.SERVER_REFLEXIVE; break; + default: assert_not_reached(); + } + + Nice.Candidate candidate = new Nice.Candidate(type); + candidate.component_id = c.component; + char[] foundation = new char[Nice.CANDIDATE_MAX_FOUNDATION]; + Memory.copy(foundation, c.foundation.data, size_t.min(c.foundation.length, Nice.CANDIDATE_MAX_FOUNDATION - 1)); + candidate.foundation = foundation; + candidate.addr = Nice.Address(); + candidate.addr.init(); + candidate.addr.set_from_string(c.ip); + candidate.addr.set_port(c.port); + candidate.priority = c.priority; + if (c.rel_addr != null) { + candidate.base_addr = Nice.Address(); + candidate.base_addr.init(); + candidate.base_addr.set_from_string(c.rel_addr); + candidate.base_addr.set_port(c.rel_port); + } + candidate.transport = Nice.CandidateTransport.UDP; + return candidate; + } + + private static JingleIceUdp.Candidate? candidate_to_jingle(Nice.Candidate nc) { + JingleIceUdp.Candidate candidate = new JingleIceUdp.Candidate(); + switch (nc.type) { + case Nice.CandidateType.HOST: candidate.type_ = JingleIceUdp.Candidate.Type.HOST; break; + case Nice.CandidateType.PEER_REFLEXIVE: candidate.type_ = JingleIceUdp.Candidate.Type.PRFLX; break; + case Nice.CandidateType.RELAYED: candidate.type_ = JingleIceUdp.Candidate.Type.RELAY; break; + case Nice.CandidateType.SERVER_REFLEXIVE: candidate.type_ = JingleIceUdp.Candidate.Type.SRFLX; break; + default: assert_not_reached(); + } + candidate.component = (uint8) nc.component_id; + candidate.foundation = ((string)nc.foundation).dup(); + candidate.generation = 0; + candidate.id = Random.next_int().to_string("%08x"); // TODO + + char[] res = new char[NICE_ADDRESS_STRING_LEN]; + nc.addr.to_string(res); + candidate.ip = (string) res; + candidate.network = 0; // TODO + candidate.port = (uint16) nc.addr.get_port(); + candidate.priority = nc.priority; + candidate.protocol = "udp"; + if (nc.base_addr.is_valid() && !nc.base_addr.equal(nc.addr)) { + res = new char[NICE_ADDRESS_STRING_LEN]; + nc.base_addr.to_string(res); + candidate.rel_addr = (string) res; + candidate.rel_port = (uint16) nc.base_addr.get_port(); + } + if (candidate.ip.has_prefix("fe80::")) return null; + + return candidate; + } + + public override void dispose() { + base.dispose(); + agent = null; + dtls_srtp_handler = null; + connections.clear(); + if (thread_loop != null) { + thread_loop.quit(); + } + } +} diff --git a/libdino/src/service/module_manager.vala b/libdino/src/service/module_manager.vala index f7cad0fe..a6efe629 100644 --- a/libdino/src/service/module_manager.vala +++ b/libdino/src/service/module_manager.vala @@ -85,7 +85,7 @@ public class ModuleManager { module_map[account].add(new Xep.InBandRegistration.Module()); module_map[account].add(new Xep.HttpFileUpload.Module()); module_map[account].add(new Xep.Reactions.Module()); - module_map[account].add(new Xep.Socks5Bytestreams.Module()); + module_map[account].add(new Xep.Socks5Bytestreams.Module.with_local_ip_address_handler(Util.get_local_ip_addresses)); module_map[account].add(new Xep.InBandBytestreams.Module()); module_map[account].add(new Xep.Jingle.Module()); module_map[account].add(new Xep.JingleSocks5Bytestreams.Module()); @@ -97,11 +97,12 @@ public class ModuleManager { module_map[account].add(new Xep.JingleMessageInitiation.Module()); module_map[account].add(new Xep.OccupantIds.Module()); module_map[account].add(new Xep.MessageRetraction.Module()); - module_map[account].add(new Xep.JingleRawUdp.Module()); + module_map[account].add(new Xep.JingleRawUdp.Module.with_local_ip_address_handler(Util.get_local_ip_addresses)); module_map[account].add(new Xep.Muji.Module()); module_map[account].add(new Xep.CallInvites.Module()); module_map[account].add(new Xep.Coin.Module()); module_map[account].add(new Xep.MessageDisplayedSynchronization.Module()); + module_map[account].add(new IceUdpModule()); initialize_account_modules(account, module_map[account]); } } diff --git a/libdino/src/service/util.vala b/libdino/src/service/util.vala index ac596cad..577bc6cc 100644 --- a/libdino/src/service/util.vala +++ b/libdino/src/service/util.vala @@ -1,8 +1,6 @@ using Dino.Entities; -namespace Dino { - -public class Util { +namespace Dino.Util { public static Message.Type get_message_type_for_conversation(Conversation conversation) { switch (conversation.type_) { case Conversation.Type.CHAT: @@ -41,6 +39,12 @@ public class Util { } return false; } -} + public static Gee.List get_local_ip_addresses() { + Gee.List result = new Gee.ArrayList(); + foreach (string ip_address in Nice.interfaces_get_local_ips(false)) { + result.add(ip_address); + } + return result; + } } diff --git a/libdino/vapi/metadata/Nice-0.1.metadata b/libdino/vapi/metadata/Nice-0.1.metadata new file mode 100644 index 00000000..7fcf046a --- /dev/null +++ b/libdino/vapi/metadata/Nice-0.1.metadata @@ -0,0 +1,11 @@ +Nice cheader_filename="nice.h" +Address.to_string.dst type="char[]" +Agent.new_reliable#constructor name="create_reliable" +Agent.attach_recv skip=false +Agent.send.buf type="uint8[]" array_length_idx=2 +AgentRecvFunc.buf type="uint8[]" array_length_idx=3 +PseudoTcpCallbacks#record skip +PseudoTcpSocket#class skip + +# Not yet supported by vapigen +# Candidate copy_function="nice_candidate_copy" free_function="nice_candidate_free" type_id="" diff --git a/libdino/vapi/nice.vapi b/libdino/vapi/nice.vapi new file mode 100644 index 00000000..540e2b4e --- /dev/null +++ b/libdino/vapi/nice.vapi @@ -0,0 +1,386 @@ +/* nice.vapi generated by vapigen, do not modify. */ + +[CCode (cprefix = "Nice", gir_namespace = "Nice", gir_version = "0.1", lower_case_cprefix = "nice_")] +namespace Nice { + [CCode (cheader_filename = "nice.h", type_id = "nice_agent_get_type ()")] + public class Agent : GLib.Object { + [CCode (has_construct_function = false)] + public Agent (GLib.MainContext ctx, Nice.Compatibility compat); + public bool add_local_address (Nice.Address addr); + public uint add_stream (uint n_components); + public bool attach_recv (uint stream_id, uint component_id, GLib.MainContext ctx, Nice.AgentRecvFunc func); + [Version (since = "0.1.16")] + public async void close_async (); + [CCode (cname = "nice_agent_new_reliable", has_construct_function = false)] + [Version (since = "0.0.11")] + public Agent.create_reliable (GLib.MainContext ctx, Nice.Compatibility compat); + [Version (since = "0.1.6")] + public bool forget_relays (uint stream_id, uint component_id); + [CCode (has_construct_function = false)] + [Version (since = "0.1.15")] + public Agent.full (GLib.MainContext ctx, Nice.Compatibility compat, Nice.AgentOption flags); + public bool gather_candidates (uint stream_id); + [Version (since = "0.1.4")] + public string generate_local_candidate_sdp (Nice.Candidate candidate); + [Version (since = "0.1.4")] + public string generate_local_sdp (); + [Version (since = "0.1.4")] + public string generate_local_stream_sdp (uint stream_id, bool include_non_ice); + [Version (since = "0.1.8")] + public Nice.ComponentState get_component_state (uint stream_id, uint component_id); + public Nice.Candidate get_default_local_candidate (uint stream_id, uint component_id); + [Version (since = "0.1.5")] + public GLib.IOStream get_io_stream (uint stream_id, uint component_id); + public GLib.SList get_local_candidates (uint stream_id, uint component_id); + public bool get_local_credentials (uint stream_id, out string ufrag, out string pwd); + public GLib.SList get_remote_candidates (uint stream_id, uint component_id); + public bool get_selected_pair (uint stream_id, uint component_id, Nice.Candidate local, Nice.Candidate remote); + [Version (since = "0.1.5")] + public GLib.Socket? get_selected_socket (uint stream_id, uint component_id); + [Version (since = "0.1.4")] + public unowned string get_stream_name (uint stream_id); + [Version (since = "0.1.4")] + public Nice.Candidate parse_remote_candidate_sdp (uint stream_id, string sdp); + [Version (since = "0.1.4")] + public int parse_remote_sdp (string sdp); + [Version (since = "0.1.4")] + public GLib.SList parse_remote_stream_sdp (uint stream_id, string sdp, string ufrag, string pwd); + [Version (since = "0.1.16")] + public bool peer_candidate_gathering_done (uint stream_id); + [Version (since = "0.1.5")] + public ssize_t recv (uint stream_id, uint component_id, [CCode (array_length_cname = "buf_len", array_length_pos = 3.5, array_length_type = "gsize")] out unowned uint8[] buf, GLib.Cancellable? cancellable = null) throws GLib.Error; + [Version (since = "0.1.5")] + public int recv_messages (uint stream_id, uint component_id, [CCode (array_length_cname = "n_messages", array_length_pos = 3.5, array_length_type = "guint")] out unowned Nice.InputMessage[] messages, GLib.Cancellable? cancellable = null) throws GLib.Error; + [Version (since = "0.1.5")] + public int recv_messages_nonblocking (uint stream_id, uint component_id, [CCode (array_length_cname = "n_messages", array_length_pos = 3.5, array_length_type = "guint")] out unowned Nice.InputMessage[] messages, GLib.Cancellable? cancellable = null) throws GLib.Error; + [Version (since = "0.1.5")] + public ssize_t recv_nonblocking (uint stream_id, uint component_id, [CCode (array_length_cname = "buf_len", array_length_pos = 3.5, array_length_type = "gsize")] out unowned uint8[] buf, GLib.Cancellable? cancellable = null) throws GLib.Error; + public void remove_stream (uint stream_id); + public bool restart (); + [Version (since = "0.1.6")] + public bool restart_stream (uint stream_id); + public int send (uint stream_id, uint component_id, [CCode (array_length_cname = "len", array_length_pos = 2.5, array_length_type = "guint", type = "const gchar*")] uint8[] buf); + [Version (since = "0.1.5")] + public int send_messages_nonblocking (uint stream_id, uint component_id, [CCode (array_length_cname = "n_messages", array_length_pos = 3.5, array_length_type = "guint")] Nice.OutputMessage[] messages, GLib.Cancellable? cancellable = null) throws GLib.Error; + public bool set_local_credentials (uint stream_id, string ufrag, string pwd); + public void set_port_range (uint stream_id, uint component_id, uint min_port, uint max_port); + public bool set_relay_info (uint stream_id, uint component_id, string server_ip, uint server_port, string username, string password, Nice.RelayType type); + public int set_remote_candidates (uint stream_id, uint component_id, GLib.SList candidates); + public bool set_remote_credentials (uint stream_id, string ufrag, string pwd); + public bool set_selected_pair (uint stream_id, uint component_id, string lfoundation, string rfoundation); + public bool set_selected_remote_candidate (uint stream_id, uint component_id, Nice.Candidate candidate); + [Version (since = "0.0.10")] + public void set_software (string software); + [Version (since = "0.1.4")] + public bool set_stream_name (uint stream_id, string name); + [Version (since = "0.0.9")] + public void set_stream_tos (uint stream_id, int tos); + [NoAccessorMethod] + [Version (since = "0.1.8")] + public bool bytestream_tcp { get; } + [NoAccessorMethod] + public uint compatibility { get; construct; } + [NoAccessorMethod] + public bool controlling_mode { get; set; } + [NoAccessorMethod] + [Version (since = "0.1.14")] + public bool force_relay { get; set; } + [NoAccessorMethod] + public bool full_mode { get; construct; } + [NoAccessorMethod] + [Version (since = "0.1.8")] + public bool ice_tcp { get; set; } + [NoAccessorMethod] + [Version (since = "0.1.16")] + public bool ice_trickle { get; set; } + [NoAccessorMethod] + [Version (since = "0.1.8")] + public bool ice_udp { get; set; } + [NoAccessorMethod] + [Version (since = "0.1.8")] + public bool keepalive_conncheck { get; set; } + [NoAccessorMethod] + public void* main_context { get; construct; } + [NoAccessorMethod] + public uint max_connectivity_checks { get; set; } + [NoAccessorMethod] + [Version (since = "0.0.4")] + public string proxy_ip { owned get; set; } + [NoAccessorMethod] + [Version (since = "0.0.4")] + public string proxy_password { owned get; set; } + [NoAccessorMethod] + [Version (since = "0.0.4")] + public uint proxy_port { get; set; } + [NoAccessorMethod] + [Version (since = "0.0.4")] + public uint proxy_type { get; set; } + [NoAccessorMethod] + [Version (since = "0.0.4")] + public string proxy_username { owned get; set; } + [NoAccessorMethod] + [Version (since = "0.0.11")] + public bool reliable { get; construct; } + [NoAccessorMethod] + [Version (since = "0.1.15")] + public uint stun_initial_timeout { get; set construct; } + [NoAccessorMethod] + [Version (since = "0.1.15")] + public uint stun_max_retransmissions { get; set construct; } + [NoAccessorMethod] + public uint stun_pacing_timer { get; set construct; } + [NoAccessorMethod] + [Version (since = "0.1.15")] + public uint stun_reliable_timeout { get; set construct; } + [NoAccessorMethod] + public string stun_server { owned get; set; } + [NoAccessorMethod] + public uint stun_server_port { get; set; } + [NoAccessorMethod] + public bool support_renomination { get; set; } + [NoAccessorMethod] + [Version (since = "0.0.7")] + public bool upnp { get; set construct; } + [NoAccessorMethod] + [Version (since = "0.0.7")] + public uint upnp_timeout { get; set construct; } + public signal void candidate_gathering_done (uint stream_id); + public signal void component_state_changed (uint stream_id, uint component_id, uint state); + public signal void initial_binding_request_received (uint stream_id); + [Version (deprecated = true, deprecated_since = "0.1.8")] + public signal void new_candidate (uint stream_id, uint component_id, string foundation); + [Version (since = "0.1.8")] + public signal void new_candidate_full (Nice.Candidate candidate); + [Version (deprecated = true, deprecated_since = "0.1.8")] + public signal void new_remote_candidate (uint stream_id, uint component_id, string foundation); + [Version (since = "0.1.8")] + public signal void new_remote_candidate_full (Nice.Candidate candidate); + [Version (deprecated = true, deprecated_since = "0.1.8")] + public signal void new_selected_pair (uint stream_id, uint component_id, string lfoundation, string rfoundation); + [Version (since = "0.1.8")] + public signal void new_selected_pair_full (uint stream_id, uint component_id, Nice.Candidate lcandidate, Nice.Candidate rcandidate); + [Version (since = "0.0.11")] + public signal void reliable_transport_writable (uint stream_id, uint component_id); + [Version (since = "0.1.5")] + public signal void streams_removed ([CCode (array_length = false, array_null_terminated = true)] uint[] stream_ids); + } + [CCode (cheader_filename = "nice.h", copy_function = "nice_candidate_copy", free_function = "nice_candidate_free")] + [Compact] + public class Candidate { + public Nice.Address addr; + public Nice.Address base_addr; + public uint component_id; + [CCode (array_length = false)] + public weak char foundation[33]; + public weak string password; + public uint32 priority; + public void* sockptr; + public uint stream_id; + public Nice.CandidateTransport transport; + public Nice.TurnServer turn; + public Nice.CandidateType type; + public weak string username; + [CCode (has_construct_function = false)] + public Candidate (Nice.CandidateType type); + public Nice.Candidate copy (); + [Version (since = "0.1.15")] + public bool equal_target (Nice.Candidate candidate2); + public void free (); + } + [CCode (cheader_filename = "nice.h", has_type_id = false)] + public struct Address { + [CCode (cname = "s.addr")] + public void* s_addr; + [CCode (cname = "s.ip4")] + public void* s_ip4; + [CCode (cname = "s.ip6")] + public void* s_ip6; + public void copy_to_sockaddr (void* sin); + public bool equal (Nice.Address b); + [Version (since = "0.1.8")] + public bool equal_no_port (Nice.Address b); + public void free (); + public uint get_port (); + public void init (); + public int ip_version (); + public bool is_private (); + public bool is_valid (); + public void set_from_sockaddr (void* sin); + public bool set_from_string (string str); + public void set_ipv4 (uint32 addr_ipv4); + public void set_ipv6 (uint8 addr_ipv6); + public void set_port (uint port); + public void to_string ([CCode (array_length = false, type = "gchar*")] char[] dst); + } + [CCode (cheader_filename = "nice.h", has_type_id = false)] + [Version (since = "0.1.5")] + public struct InputMessage { + [CCode (array_length_cname = "n_buffers")] + public weak GLib.InputVector[] buffers; + public int n_buffers; + public Nice.Address from; + public size_t length; + } + [CCode (cheader_filename = "nice.h", has_type_id = false)] + [Version (since = "0.1.5")] + public struct OutputMessage { + [CCode (array_length_cname = "n_buffers")] + public weak GLib.OutputVector[] buffers; + public int n_buffers; + } + [CCode (cheader_filename = "nice.h", cname = "TurnServer", has_type_id = false)] + public struct TurnServer { + public int ref_count; + public Nice.Address server; + public weak string username; + public weak string password; + public Nice.RelayType type; + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_AGENT_OPTION_", has_type_id = false)] + [Flags] + [Version (since = "0.1.15")] + public enum AgentOption { + REGULAR_NOMINATION, + RELIABLE, + LITE_MODE, + ICE_TRICKLE, + SUPPORT_RENOMINATION + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_CANDIDATE_TRANSPORT_", has_type_id = false)] + public enum CandidateTransport { + UDP, + TCP_ACTIVE, + TCP_PASSIVE, + TCP_SO + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_CANDIDATE_TYPE_", has_type_id = false)] + public enum CandidateType { + HOST, + SERVER_REFLEXIVE, + PEER_REFLEXIVE, + RELAYED + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_COMPATIBILITY_", has_type_id = false)] + public enum Compatibility { + RFC5245, + DRAFT19, + GOOGLE, + MSN, + WLM2009, + OC2007, + OC2007R2, + LAST + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_COMPONENT_STATE_", has_type_id = false)] + public enum ComponentState { + DISCONNECTED, + GATHERING, + CONNECTING, + CONNECTED, + READY, + FAILED, + LAST; + [Version (since = "0.1.6")] + public unowned string to_string (); + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_COMPONENT_TYPE_", has_type_id = false)] + public enum ComponentType { + RTP, + RTCP + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_NOMINATION_MODE_", has_type_id = false)] + [Version (since = "0.1.15")] + public enum NominationMode { + REGULAR, + AGGRESSIVE + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_PROXY_TYPE_", has_type_id = false)] + [Version (since = "0.0.4")] + public enum ProxyType { + NONE, + SOCKS5, + HTTP, + LAST + } + [CCode (cheader_filename = "nice.h", cname = "PseudoTcpDebugLevel", cprefix = "PSEUDO_TCP_DEBUG_", has_type_id = false)] + [Version (since = "0.0.11")] + public enum PseudoTcpDebugLevel { + NONE, + NORMAL, + VERBOSE + } + [CCode (cheader_filename = "nice.h", cname = "PseudoTcpShutdown", cprefix = "PSEUDO_TCP_SHUTDOWN_", has_type_id = false)] + [Version (since = "0.1.8")] + public enum PseudoTcpShutdown { + RD, + WR, + RDWR + } + [CCode (cheader_filename = "nice.h", cname = "PseudoTcpState", cprefix = "PSEUDO_TCP_", has_type_id = false)] + [Version (since = "0.0.11")] + public enum PseudoTcpState { + LISTEN, + SYN_SENT, + SYN_RECEIVED, + ESTABLISHED, + CLOSED, + FIN_WAIT_1, + FIN_WAIT_2, + CLOSING, + TIME_WAIT, + CLOSE_WAIT, + LAST_ACK + } + [CCode (cheader_filename = "nice.h", cname = "PseudoTcpWriteResult", cprefix = "WR_", has_type_id = false)] + [Version (since = "0.0.11")] + public enum PseudoTcpWriteResult { + SUCCESS, + TOO_LARGE, + FAIL + } + [CCode (cheader_filename = "nice.h", cprefix = "NICE_RELAY_TYPE_TURN_", has_type_id = false)] + public enum RelayType { + UDP, + TCP, + TLS + } + [CCode (cheader_filename = "nice.h", instance_pos = 4.9)] + public delegate void AgentRecvFunc (Nice.Agent agent, uint stream_id, uint component_id, [CCode (array_length_cname = "len", array_length_pos = 3.5, array_length_type = "guint", type = "gchar*")] uint8[] buf); + [CCode (cheader_filename = "nice.h", cname = "NICE_AGENT_MAX_REMOTE_CANDIDATES")] + public const int AGENT_MAX_REMOTE_CANDIDATES; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_DIRECTION_MS_PREF_ACTIVE")] + public const int CANDIDATE_DIRECTION_MS_PREF_ACTIVE; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_DIRECTION_MS_PREF_PASSIVE")] + public const int CANDIDATE_DIRECTION_MS_PREF_PASSIVE; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_MAX_FOUNDATION")] + public const int CANDIDATE_MAX_FOUNDATION; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TRANSPORT_MS_PREF_TCP")] + public const int CANDIDATE_TRANSPORT_MS_PREF_TCP; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TRANSPORT_MS_PREF_UDP")] + public const int CANDIDATE_TRANSPORT_MS_PREF_UDP; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_HOST")] + public const int CANDIDATE_TYPE_PREF_HOST; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_NAT_ASSISTED")] + public const int CANDIDATE_TYPE_PREF_NAT_ASSISTED; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_PEER_REFLEXIVE")] + public const int CANDIDATE_TYPE_PREF_PEER_REFLEXIVE; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_RELAYED")] + public const int CANDIDATE_TYPE_PREF_RELAYED; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_RELAYED_UDP")] + public const int CANDIDATE_TYPE_PREF_RELAYED_UDP; + [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_SERVER_REFLEXIVE")] + public const int CANDIDATE_TYPE_PREF_SERVER_REFLEXIVE; + [CCode (cheader_filename = "nice.h")] + public static void debug_disable (bool with_stun); + [CCode (cheader_filename = "nice.h")] + public static void debug_enable (bool with_stun); + [CCode (cheader_filename = "nice.h")] + public static string? interfaces_get_ip_for_interface (string interface_name); + [CCode (cheader_filename = "nice.h")] + public static GLib.List interfaces_get_local_interfaces (); + [CCode (cheader_filename = "nice.h")] + public static GLib.List interfaces_get_local_ips (bool include_loopback); + [CCode (cheader_filename = "nice.h", cname = "pseudo_tcp_set_debug_level")] + [Version (since = "0.0.11")] + public static void pseudo_tcp_set_debug_level (Nice.PseudoTcpDebugLevel level); +} diff --git a/plugins/ice/meson.build b/plugins/ice/meson.build deleted file mode 100644 index 19030259..00000000 --- a/plugins/ice/meson.build +++ /dev/null @@ -1,25 +0,0 @@ -dependencies = [ - dep_dino, - dep_gee, - dep_gio, - dep_glib, - dep_gmodule, - dep_nice, - dep_xmpp_vala, -] -sources = files( - 'src/module.vala', - 'src/plugin.vala', - 'src/transport_parameters.vala', - 'src/util.vala', - 'src/register_plugin.vala', -) -c_args = vala_c_args + [ - '-DG_LOG_DOMAIN="ice"', -] -vala_args = [ - '--vapidir', meson.current_source_dir() / 'vapi', -] -lib_ice = shared_library('ice', sources, name_prefix: '', c_args: c_args, vala_args: vala_args, include_directories: include_directories('src'), dependencies: dependencies, install: true, install_dir: get_option('libdir') / get_option('plugindir'), install_rpath: default_install_rpath) -dep_ice = declare_dependency(link_with: lib_ice, include_directories: include_directories('.')) -summary('Peer-to-peer communication (ice)', dep_ice.found(), bool_yn: true, section: 'Plugins') diff --git a/plugins/ice/src/module.vala b/plugins/ice/src/module.vala deleted file mode 100644 index c3c92124..00000000 --- a/plugins/ice/src/module.vala +++ /dev/null @@ -1,57 +0,0 @@ -using Gee; - -using Dino.Crypto; -using Xmpp; -using Xmpp.Xep; - -public class Dino.Plugins.Ice.Module : JingleIceUdp.Module { - - public string? stun_ip = null; - public uint stun_port = 0; - public string? turn_ip = null; - public Xep.ExternalServiceDiscovery.Service? turn_service = null; - - private weak Nice.Agent? agent; - private HashMap cerds = new HashMap(); - - private Nice.Agent get_agent() { - Nice.Agent? agent = this.agent; - if (agent == null) { - agent = new Nice.Agent(MainContext.@default(), Nice.Compatibility.RFC5245); - if (stun_ip != null) { - agent.stun_server = stun_ip; - agent.stun_server_port = stun_port; - } - agent.ice_tcp = false; - agent.set_software("Dino"); - agent.weak_ref(agent_unweak); - this.agent = agent; - debug("STUN server for libnice %s %u", agent.stun_server, agent.stun_server_port); - } - return agent; - } - - public override Jingle.TransportParameters create_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid) { - DtlsSrtp.CredentialsCapsule? cred = get_create_credentials(local_full_jid, peer_full_jid); - return new TransportParameters(get_agent(), cred, turn_service, turn_ip, components, local_full_jid, peer_full_jid); - } - - public override Jingle.TransportParameters parse_transport_parameters(XmppStream stream, uint8 components, Jid local_full_jid, Jid peer_full_jid, StanzaNode transport) throws Jingle.IqError { - DtlsSrtp.CredentialsCapsule? cred = get_create_credentials(local_full_jid, peer_full_jid); - return new TransportParameters(get_agent(), cred, turn_service, turn_ip, components, local_full_jid, peer_full_jid, transport); - } - - private DtlsSrtp.CredentialsCapsule? get_create_credentials(Jid local_full_jid, Jid peer_full_jid) { - string from_to_id = local_full_jid.to_string() + peer_full_jid.to_string(); - try { - if (!cerds.has_key(from_to_id)) cerds[from_to_id] = DtlsSrtp.generate_credentials(); - } catch (GLib.Error e) { - warning("Error creating dtls credentials: %s", e.message); - } - return cerds[from_to_id]; - } - - private void agent_unweak() { - this.agent = null; - } -} \ No newline at end of file diff --git a/plugins/ice/src/plugin.vala b/plugins/ice/src/plugin.vala deleted file mode 100644 index d1655a74..00000000 --- a/plugins/ice/src/plugin.vala +++ /dev/null @@ -1,104 +0,0 @@ -using Gee; -using Dino.Entities; -using Xmpp; -using Xmpp.Xep; - -private extern const size_t NICE_ADDRESS_STRING_LEN; - -public class Dino.Plugins.Ice.Plugin : RootInterface, Object { - private HashMap timeouts = new HashMap(Account.hash_func, Account.equals_func); - - 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) => { - if (stream.get_module(Socks5Bytestreams.Module.IDENTITY) != null) { - stream.get_module(Socks5Bytestreams.Module.IDENTITY).set_local_ip_address_handler(get_local_ip_addresses); - } - if (stream.get_module(JingleRawUdp.Module.IDENTITY) != null) { - stream.get_module(JingleRawUdp.Module.IDENTITY).set_local_ip_address_handler(get_local_ip_addresses); - } - }); - app.stream_interactor.stream_negotiated.connect(external_discovery_refresh_services); - } - - private async void external_discovery_refresh_services(Account account, XmppStream stream) { - Module? ice_udp_module = stream.get_module(JingleIceUdp.Module.IDENTITY) as Module; - if (ice_udp_module == null) return; - - Gee.List 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 (ip.is_any || ip.is_link_local || ip.is_loopback || ip.is_multicast || ip.is_site_local) { - warning("Ignoring STUN/TURN server at %s", service.host); - 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.dino.im"); - if (ip == null) return; - - debug("Using fallback STUN server: stun.dino.im:7886, resolved to %s", ip.to_string()); - - ice_udp_module.stun_ip = ip.to_string(); - ice_udp_module.stun_port = 7886; - } - - // Refresh TURN credentials before they expire - if (ice_udp_module.turn_service != null) { - DateTime? expires = ice_udp_module.turn_service.expires; - if (expires != null) { - uint refresh_delay = (uint) (expires.to_unix() - new DateTime.now_utc().to_unix()) / 2; - - if (refresh_delay >= 300 && refresh_delay <= (int64) uint.MAX) { // 5 min < refetch < max - debug("Re-fetching TURN credentials in %u sec", refresh_delay); - - timeouts.unset(account); - timeouts[account] = Timeout.add_seconds((uint) refresh_delay, () => { - external_discovery_refresh_services.begin(account, stream); - return false; - }); - } else { - warning("TURN credentials' expiry time = %u, *not* re-fetching", refresh_delay); - } - } - } - } - - public void shutdown() { - // Nothing to do - } - - private async InetAddress? lookup_ipv4_addess(string host) { - try { - Resolver resolver = Resolver.get_default(); - GLib.List? 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 diff --git a/plugins/ice/src/register_plugin.vala b/plugins/ice/src/register_plugin.vala deleted file mode 100644 index b2ed56c1..00000000 --- a/plugins/ice/src/register_plugin.vala +++ /dev/null @@ -1,3 +0,0 @@ -public Type register_plugin(Module module) { - return typeof (Dino.Plugins.Ice.Plugin); -} diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala deleted file mode 100644 index 122207c5..00000000 --- a/plugins/ice/src/transport_parameters.vala +++ /dev/null @@ -1,391 +0,0 @@ -using Gee; - -using Dino.Crypto; -using Xmpp; -using Xmpp.Xep; - - -public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransportParameters { - private Nice.Agent agent; - private uint stream_id; - private bool we_want_connection; - private bool remote_credentials_set; - private Map connections = new HashMap(); - private DtlsSrtp.Handler? dtls_srtp_handler; - private MainContext thread_context; - private MainLoop thread_loop; - - private class DatagramConnection : Jingle.DatagramConnection { - private Nice.Agent agent; - private DtlsSrtp.Handler? dtls_srtp_handler; - private uint stream_id; - private string? error; - private ulong datagram_received_id; - - public DatagramConnection(Nice.Agent agent, DtlsSrtp.Handler? dtls_srtp_handler, uint stream_id, uint8 component_id) { - this.agent = agent; - this.dtls_srtp_handler = dtls_srtp_handler; - this.stream_id = stream_id; - this.component_id = component_id; - this.datagram_received_id = this.datagram_received.connect((datagram) => { - bytes_received += datagram.length; - }); - } - - public override async void terminate(bool we_terminated, string? reason_string = null, string? reason_text = null) { - yield base.terminate(we_terminated, reason_string, reason_text); - this.disconnect(datagram_received_id); - agent = null; - dtls_srtp_handler = null; - } - - public override void send_datagram(Bytes datagram) { - if (this.agent != null && is_component_ready(agent, stream_id, component_id)) { - try { - if (dtls_srtp_handler != null) { - uint8[] encrypted_data = dtls_srtp_handler.process_outgoing_data(component_id, datagram.get_data()); - if (encrypted_data == null) return; - GLib.OutputVector vector = { encrypted_data, encrypted_data.length }; - GLib.OutputVector[] vectors = { vector }; - Nice.OutputMessage message = { vectors }; - Nice.OutputMessage[] messages = { message }; - agent.send_messages_nonblocking(stream_id, component_id, messages); - } else { - GLib.OutputVector vector = { datagram.get_data(), datagram.get_size() }; - GLib.OutputVector[] vectors = { vector }; - Nice.OutputMessage message = { vectors }; - Nice.OutputMessage[] messages = { message }; - agent.send_messages_nonblocking(stream_id, component_id, messages); - } - bytes_sent += datagram.length; - } catch (GLib.Error e) { - warning("%s while send_datagram stream %u component %u", e.message, stream_id, component_id); - } - } - } - } - - public TransportParameters(Nice.Agent agent, DtlsSrtp.CredentialsCapsule? credentials, Xep.ExternalServiceDiscovery.Service? turn_service, string? turn_ip, uint8 components, Jid local_full_jid, Jid peer_full_jid, StanzaNode? node = null) { - base(components, local_full_jid, peer_full_jid, node); - this.we_want_connection = (node == null); - this.agent = agent; - - if (this.peer_fingerprint != null || !incoming) { - dtls_srtp_handler = setup_dtls(this, credentials); - own_fingerprint = dtls_srtp_handler.own_fingerprint; - if (incoming) { - own_setup = "active"; - dtls_srtp_handler.mode = DtlsSrtp.Mode.CLIENT; - dtls_srtp_handler.peer_fingerprint = peer_fingerprint; - dtls_srtp_handler.peer_fp_algo = peer_fp_algo; - } else { - own_setup = "actpass"; - dtls_srtp_handler.mode = DtlsSrtp.Mode.SERVER; - dtls_srtp_handler.setup_dtls_connection.begin((_, res) => { - var content_encryption = dtls_srtp_handler.setup_dtls_connection.end(res); - if (content_encryption != null) { - this.content.encryptions[content_encryption.encryption_ns] = content_encryption; - } - }); - } - } - - agent.candidate_gathering_done.connect(on_candidate_gathering_done); - agent.initial_binding_request_received.connect(on_initial_binding_request_received); - agent.component_state_changed.connect(on_component_state_changed); - agent.new_selected_pair_full.connect(on_new_selected_pair_full); - agent.new_candidate_full.connect(on_new_candidate); - - agent.controlling_mode = !incoming; - stream_id = agent.add_stream(components); - thread_context = new MainContext(); - new Thread(@"ice-thread-$stream_id", () => { - thread_context.push_thread_default(); - thread_loop = new MainLoop(thread_context, false); - thread_loop.run(); - thread_context.pop_thread_default(); - return null; - }); - - if (turn_ip != null) { - for (uint8 component_id = 1; component_id <= components; component_id++) { - agent.set_relay_info(stream_id, component_id, turn_ip, turn_service.port, turn_service.username, turn_service.password, Nice.RelayType.UDP); - debug("TURN info (component %i) %s:%u", component_id, turn_ip, turn_service.port); - } - } - string ufrag; - string pwd; - agent.get_local_credentials(stream_id, out ufrag, out pwd); - init(ufrag, pwd); - - for (uint8 component_id = 1; component_id <= components; component_id++) { - // We don't properly get local candidates before this call - agent.attach_recv(stream_id, component_id, thread_context, on_recv); - } - - agent.gather_candidates(stream_id); - } - - private static DtlsSrtp.Handler setup_dtls(TransportParameters tp, DtlsSrtp.CredentialsCapsule credentials) { - var weak_self = WeakRef(tp); - DtlsSrtp.Handler dtls_srtp = new DtlsSrtp.Handler.with_cert(credentials); - dtls_srtp.send_data.connect((data) => { - TransportParameters self = (TransportParameters) weak_self.get(); - if (self != null) self.agent.send(self.stream_id, 1, data); - }); - return dtls_srtp; - } - - private void on_candidate_gathering_done(uint stream_id) { - if (stream_id != this.stream_id) return; - debug("on_candidate_gathering_done in %u", stream_id); - - for (uint8 i = 1; i <= components; i++) { - foreach (unowned Nice.Candidate nc in agent.get_local_candidates(stream_id, i)) { - if (nc.transport == Nice.CandidateTransport.UDP) { - JingleIceUdp.Candidate? candidate = candidate_to_jingle(nc); - if (candidate == null) continue; - debug("Local candidate summary: %s", agent.generate_local_candidate_sdp(nc)); - } - } - } - } - - private void on_new_candidate(Nice.Candidate nc) { - if (nc.stream_id != stream_id) return; - JingleIceUdp.Candidate? candidate = candidate_to_jingle(nc); - if (candidate == null) return; - - if (nc.transport == Nice.CandidateTransport.UDP) { - // Execution was in the agent thread before - add_local_candidate_threadsafe(candidate); - } - } - - private bool bytes_equal(uint8[] a1, uint8[] a2) { - return a1.length == a2.length && Memory.cmp(a1, a2, a1.length) == 0; - } - - public override void handle_transport_accept(StanzaNode transport) throws Jingle.IqError { - debug("on_transport_accept from %s", peer_full_jid.to_string()); - base.handle_transport_accept(transport); - - if (dtls_srtp_handler != null && peer_fingerprint != null) { - if (dtls_srtp_handler.peer_fingerprint != null) { - if (!bytes_equal(dtls_srtp_handler.peer_fingerprint, peer_fingerprint)) { - warning("Tried to replace certificate fingerprint mid use. We don't allow that."); - peer_fingerprint = dtls_srtp_handler.peer_fingerprint; - peer_fp_algo = dtls_srtp_handler.peer_fp_algo; - } - } else { - dtls_srtp_handler.peer_fingerprint = peer_fingerprint; - dtls_srtp_handler.peer_fp_algo = peer_fp_algo; - } - if (peer_setup == "passive") { - dtls_srtp_handler.mode = DtlsSrtp.Mode.CLIENT; - dtls_srtp_handler.stop_dtls_connection(); - dtls_srtp_handler.setup_dtls_connection.begin((_, res) => { - var content_encryption = dtls_srtp_handler.setup_dtls_connection.end(res); - if (content_encryption != null) { - this.content.encryptions[content_encryption.encryption_ns] = content_encryption; - } - }); - } - } else { - dtls_srtp_handler = null; - } - } - - public override void handle_transport_info(StanzaNode transport) throws Jingle.IqError { - debug("on_transport_info from %s", peer_full_jid.to_string()); - base.handle_transport_info(transport); - - if (dtls_srtp_handler != null && peer_fingerprint != null) { - if (dtls_srtp_handler.peer_fingerprint != null) { - if (!bytes_equal(dtls_srtp_handler.peer_fingerprint, peer_fingerprint)) { - warning("Tried to replace certificate fingerprint mid use. We don't allow that."); - peer_fingerprint = dtls_srtp_handler.peer_fingerprint; - peer_fp_algo = dtls_srtp_handler.peer_fp_algo; - } - } else { - dtls_srtp_handler.peer_fingerprint = peer_fingerprint; - dtls_srtp_handler.peer_fp_algo = peer_fp_algo; - } - } - - if (!we_want_connection) return; - - if (remote_ufrag != null && remote_pwd != null && !remote_credentials_set) { - agent.set_remote_credentials(stream_id, remote_ufrag, remote_pwd); - remote_credentials_set = true; - } - for (uint8 i = 1; i <= components; i++) { - SList candidates = new SList(); - foreach (JingleIceUdp.Candidate candidate in remote_candidates) { - if (candidate.component == i) { - candidates.append(candidate_to_nice(candidate)); - } - } - int new_candidates = agent.set_remote_candidates(stream_id, i, candidates); - debug("Updated to %i remote candidates for candidate %u via transport info", new_candidates, i); - } - } - - public override void create_transport_connection(XmppStream stream, Jingle.Content content) { - debug("create_transport_connection: %s", content.session.sid); - debug("local_credentials: %s %s", local_ufrag, local_pwd); - debug("remote_credentials: %s %s", remote_ufrag, remote_pwd); - debug("expected incoming credentials: %s %s", local_ufrag + ":" + remote_ufrag, local_pwd); - debug("expected outgoing credentials: %s %s", remote_ufrag + ":" + local_ufrag, remote_pwd); - - we_want_connection = true; - - if (remote_ufrag != null && remote_pwd != null && !remote_credentials_set) { - agent.set_remote_credentials(stream_id, remote_ufrag, remote_pwd); - remote_credentials_set = true; - } - for (uint8 i = 1; i <= components; i++) { - SList candidates = new SList(); - foreach (JingleIceUdp.Candidate candidate in remote_candidates) { - if (candidate.ip.has_prefix("fe80::")) continue; - if (candidate.component == i) { - candidates.append(candidate_to_nice(candidate)); - debug("remote candidate: %s", agent.generate_local_candidate_sdp(candidate_to_nice(candidate))); - } - } - int new_candidates = agent.set_remote_candidates(stream_id, i, candidates); - debug("Initiated component %u with %i remote candidates", i, new_candidates); - - connections[i] = new DatagramConnection(agent, dtls_srtp_handler, stream_id, i); - content.set_transport_connection(connections[i], i); - } - - base.create_transport_connection(stream, content); - } - - private void on_component_state_changed(uint stream_id, uint component_id, uint state) { - if (stream_id != this.stream_id) return; - debug("stream %u component %u state changed to %s", stream_id, component_id, agent.get_component_state(stream_id, component_id).to_string()); - may_consider_ready(stream_id, component_id); - if (incoming && dtls_srtp_handler != null && !dtls_srtp_handler.ready && is_component_ready(agent, stream_id, component_id) && dtls_srtp_handler.mode == DtlsSrtp.Mode.CLIENT) { - dtls_srtp_handler.setup_dtls_connection.begin((_, res) => { - Jingle.ContentEncryption? encryption = dtls_srtp_handler.setup_dtls_connection.end(res); - if (encryption != null) { - this.content.encryptions[encryption.encryption_ns] = encryption; - } - }); - } - } - - private void may_consider_ready(uint stream_id, uint component_id) { - if (stream_id != this.stream_id) return; - if (connections.has_key((uint8) component_id) && !connections[(uint8)component_id].ready && is_component_ready(agent, stream_id, component_id) && (dtls_srtp_handler == null || dtls_srtp_handler.ready)) { - connections[(uint8)component_id].ready = true; - } - } - - private void on_initial_binding_request_received(uint stream_id) { - if (stream_id != this.stream_id) return; - debug("initial_binding_request_received"); - } - - private void on_new_selected_pair_full(uint stream_id, uint component_id, Nice.Candidate p1, Nice.Candidate p2) { - if (stream_id != this.stream_id) return; - debug("new_selected_pair_full %u [%s, %s]", component_id, agent.generate_local_candidate_sdp(p1), agent.generate_local_candidate_sdp(p2)); - } - - private void on_recv(Nice.Agent agent, uint stream_id, uint component_id, uint8[] data) { - if (stream_id != this.stream_id) return; - uint8[] decrypt_data = null; - if (dtls_srtp_handler != null) { - try { - decrypt_data = dtls_srtp_handler.process_incoming_data(component_id, data); - if (decrypt_data == null) return; - } catch (Crypto.Error e) { - warning("%s while on_recv stream %u component %u", e.message, stream_id, component_id); - return; - } - } - may_consider_ready(stream_id, component_id); - if (connections.has_key((uint8) component_id)) { - if (!connections[(uint8) component_id].ready) { - debug("on_recv stream %u component %u when state %s", stream_id, component_id, agent.get_component_state(stream_id, component_id).to_string()); - } - connections[(uint8) component_id].datagram_received(new Bytes(decrypt_data ?? data)); - } else { - debug("on_recv stream %u component %u length %u", stream_id, component_id, data.length); - } - } - - private static Nice.Candidate candidate_to_nice(JingleIceUdp.Candidate c) { - Nice.CandidateType type; - switch (c.type_) { - case JingleIceUdp.Candidate.Type.HOST: type = Nice.CandidateType.HOST; break; - case JingleIceUdp.Candidate.Type.PRFLX: type = Nice.CandidateType.PEER_REFLEXIVE; break; - case JingleIceUdp.Candidate.Type.RELAY: type = Nice.CandidateType.RELAYED; break; - case JingleIceUdp.Candidate.Type.SRFLX: type = Nice.CandidateType.SERVER_REFLEXIVE; break; - default: assert_not_reached(); - } - - Nice.Candidate candidate = new Nice.Candidate(type); - candidate.component_id = c.component; - char[] foundation = new char[Nice.CANDIDATE_MAX_FOUNDATION]; - Memory.copy(foundation, c.foundation.data, size_t.min(c.foundation.length, Nice.CANDIDATE_MAX_FOUNDATION - 1)); - candidate.foundation = foundation; - candidate.addr = Nice.Address(); - candidate.addr.init(); - candidate.addr.set_from_string(c.ip); - candidate.addr.set_port(c.port); - candidate.priority = c.priority; - if (c.rel_addr != null) { - candidate.base_addr = Nice.Address(); - candidate.base_addr.init(); - candidate.base_addr.set_from_string(c.rel_addr); - candidate.base_addr.set_port(c.rel_port); - } - candidate.transport = Nice.CandidateTransport.UDP; - return candidate; - } - - private static JingleIceUdp.Candidate? candidate_to_jingle(Nice.Candidate nc) { - JingleIceUdp.Candidate candidate = new JingleIceUdp.Candidate(); - switch (nc.type) { - case Nice.CandidateType.HOST: candidate.type_ = JingleIceUdp.Candidate.Type.HOST; break; - case Nice.CandidateType.PEER_REFLEXIVE: candidate.type_ = JingleIceUdp.Candidate.Type.PRFLX; break; - case Nice.CandidateType.RELAYED: candidate.type_ = JingleIceUdp.Candidate.Type.RELAY; break; - case Nice.CandidateType.SERVER_REFLEXIVE: candidate.type_ = JingleIceUdp.Candidate.Type.SRFLX; break; - default: assert_not_reached(); - } - candidate.component = (uint8) nc.component_id; - candidate.foundation = ((string)nc.foundation).dup(); - candidate.generation = 0; - candidate.id = Random.next_int().to_string("%08x"); // TODO - - char[] res = new char[NICE_ADDRESS_STRING_LEN]; - nc.addr.to_string(res); - candidate.ip = (string) res; - candidate.network = 0; // TODO - candidate.port = (uint16) nc.addr.get_port(); - candidate.priority = nc.priority; - candidate.protocol = "udp"; - if (nc.base_addr.is_valid() && !nc.base_addr.equal(nc.addr)) { - res = new char[NICE_ADDRESS_STRING_LEN]; - nc.base_addr.to_string(res); - candidate.rel_addr = (string) res; - candidate.rel_port = (uint16) nc.base_addr.get_port(); - } - if (candidate.ip.has_prefix("fe80::")) return null; - - return candidate; - } - - public override void dispose() { - base.dispose(); - agent = null; - dtls_srtp_handler = null; - connections.clear(); - if (thread_loop != null) { - thread_loop.quit(); - } - } -} diff --git a/plugins/ice/src/util.vala b/plugins/ice/src/util.vala deleted file mode 100644 index dd89d2f4..00000000 --- a/plugins/ice/src/util.vala +++ /dev/null @@ -1,18 +0,0 @@ -using Gee; - -namespace Dino.Plugins.Ice { - -internal static bool is_component_ready(Nice.Agent agent, uint stream_id, uint component_id) { - var state = agent.get_component_state(stream_id, component_id); - return state == Nice.ComponentState.CONNECTED || state == Nice.ComponentState.READY; -} - -internal Gee.List get_local_ip_addresses() { - Gee.List result = new ArrayList(); - foreach (string ip_address in Nice.interfaces_get_local_ips(false)) { - result.add(ip_address); - } - return result; -} - -} \ No newline at end of file diff --git a/plugins/ice/vapi/metadata/Nice-0.1.metadata b/plugins/ice/vapi/metadata/Nice-0.1.metadata deleted file mode 100644 index 7fcf046a..00000000 --- a/plugins/ice/vapi/metadata/Nice-0.1.metadata +++ /dev/null @@ -1,11 +0,0 @@ -Nice cheader_filename="nice.h" -Address.to_string.dst type="char[]" -Agent.new_reliable#constructor name="create_reliable" -Agent.attach_recv skip=false -Agent.send.buf type="uint8[]" array_length_idx=2 -AgentRecvFunc.buf type="uint8[]" array_length_idx=3 -PseudoTcpCallbacks#record skip -PseudoTcpSocket#class skip - -# Not yet supported by vapigen -# Candidate copy_function="nice_candidate_copy" free_function="nice_candidate_free" type_id="" diff --git a/plugins/ice/vapi/nice.vapi b/plugins/ice/vapi/nice.vapi deleted file mode 100644 index 540e2b4e..00000000 --- a/plugins/ice/vapi/nice.vapi +++ /dev/null @@ -1,386 +0,0 @@ -/* nice.vapi generated by vapigen, do not modify. */ - -[CCode (cprefix = "Nice", gir_namespace = "Nice", gir_version = "0.1", lower_case_cprefix = "nice_")] -namespace Nice { - [CCode (cheader_filename = "nice.h", type_id = "nice_agent_get_type ()")] - public class Agent : GLib.Object { - [CCode (has_construct_function = false)] - public Agent (GLib.MainContext ctx, Nice.Compatibility compat); - public bool add_local_address (Nice.Address addr); - public uint add_stream (uint n_components); - public bool attach_recv (uint stream_id, uint component_id, GLib.MainContext ctx, Nice.AgentRecvFunc func); - [Version (since = "0.1.16")] - public async void close_async (); - [CCode (cname = "nice_agent_new_reliable", has_construct_function = false)] - [Version (since = "0.0.11")] - public Agent.create_reliable (GLib.MainContext ctx, Nice.Compatibility compat); - [Version (since = "0.1.6")] - public bool forget_relays (uint stream_id, uint component_id); - [CCode (has_construct_function = false)] - [Version (since = "0.1.15")] - public Agent.full (GLib.MainContext ctx, Nice.Compatibility compat, Nice.AgentOption flags); - public bool gather_candidates (uint stream_id); - [Version (since = "0.1.4")] - public string generate_local_candidate_sdp (Nice.Candidate candidate); - [Version (since = "0.1.4")] - public string generate_local_sdp (); - [Version (since = "0.1.4")] - public string generate_local_stream_sdp (uint stream_id, bool include_non_ice); - [Version (since = "0.1.8")] - public Nice.ComponentState get_component_state (uint stream_id, uint component_id); - public Nice.Candidate get_default_local_candidate (uint stream_id, uint component_id); - [Version (since = "0.1.5")] - public GLib.IOStream get_io_stream (uint stream_id, uint component_id); - public GLib.SList get_local_candidates (uint stream_id, uint component_id); - public bool get_local_credentials (uint stream_id, out string ufrag, out string pwd); - public GLib.SList get_remote_candidates (uint stream_id, uint component_id); - public bool get_selected_pair (uint stream_id, uint component_id, Nice.Candidate local, Nice.Candidate remote); - [Version (since = "0.1.5")] - public GLib.Socket? get_selected_socket (uint stream_id, uint component_id); - [Version (since = "0.1.4")] - public unowned string get_stream_name (uint stream_id); - [Version (since = "0.1.4")] - public Nice.Candidate parse_remote_candidate_sdp (uint stream_id, string sdp); - [Version (since = "0.1.4")] - public int parse_remote_sdp (string sdp); - [Version (since = "0.1.4")] - public GLib.SList parse_remote_stream_sdp (uint stream_id, string sdp, string ufrag, string pwd); - [Version (since = "0.1.16")] - public bool peer_candidate_gathering_done (uint stream_id); - [Version (since = "0.1.5")] - public ssize_t recv (uint stream_id, uint component_id, [CCode (array_length_cname = "buf_len", array_length_pos = 3.5, array_length_type = "gsize")] out unowned uint8[] buf, GLib.Cancellable? cancellable = null) throws GLib.Error; - [Version (since = "0.1.5")] - public int recv_messages (uint stream_id, uint component_id, [CCode (array_length_cname = "n_messages", array_length_pos = 3.5, array_length_type = "guint")] out unowned Nice.InputMessage[] messages, GLib.Cancellable? cancellable = null) throws GLib.Error; - [Version (since = "0.1.5")] - public int recv_messages_nonblocking (uint stream_id, uint component_id, [CCode (array_length_cname = "n_messages", array_length_pos = 3.5, array_length_type = "guint")] out unowned Nice.InputMessage[] messages, GLib.Cancellable? cancellable = null) throws GLib.Error; - [Version (since = "0.1.5")] - public ssize_t recv_nonblocking (uint stream_id, uint component_id, [CCode (array_length_cname = "buf_len", array_length_pos = 3.5, array_length_type = "gsize")] out unowned uint8[] buf, GLib.Cancellable? cancellable = null) throws GLib.Error; - public void remove_stream (uint stream_id); - public bool restart (); - [Version (since = "0.1.6")] - public bool restart_stream (uint stream_id); - public int send (uint stream_id, uint component_id, [CCode (array_length_cname = "len", array_length_pos = 2.5, array_length_type = "guint", type = "const gchar*")] uint8[] buf); - [Version (since = "0.1.5")] - public int send_messages_nonblocking (uint stream_id, uint component_id, [CCode (array_length_cname = "n_messages", array_length_pos = 3.5, array_length_type = "guint")] Nice.OutputMessage[] messages, GLib.Cancellable? cancellable = null) throws GLib.Error; - public bool set_local_credentials (uint stream_id, string ufrag, string pwd); - public void set_port_range (uint stream_id, uint component_id, uint min_port, uint max_port); - public bool set_relay_info (uint stream_id, uint component_id, string server_ip, uint server_port, string username, string password, Nice.RelayType type); - public int set_remote_candidates (uint stream_id, uint component_id, GLib.SList candidates); - public bool set_remote_credentials (uint stream_id, string ufrag, string pwd); - public bool set_selected_pair (uint stream_id, uint component_id, string lfoundation, string rfoundation); - public bool set_selected_remote_candidate (uint stream_id, uint component_id, Nice.Candidate candidate); - [Version (since = "0.0.10")] - public void set_software (string software); - [Version (since = "0.1.4")] - public bool set_stream_name (uint stream_id, string name); - [Version (since = "0.0.9")] - public void set_stream_tos (uint stream_id, int tos); - [NoAccessorMethod] - [Version (since = "0.1.8")] - public bool bytestream_tcp { get; } - [NoAccessorMethod] - public uint compatibility { get; construct; } - [NoAccessorMethod] - public bool controlling_mode { get; set; } - [NoAccessorMethod] - [Version (since = "0.1.14")] - public bool force_relay { get; set; } - [NoAccessorMethod] - public bool full_mode { get; construct; } - [NoAccessorMethod] - [Version (since = "0.1.8")] - public bool ice_tcp { get; set; } - [NoAccessorMethod] - [Version (since = "0.1.16")] - public bool ice_trickle { get; set; } - [NoAccessorMethod] - [Version (since = "0.1.8")] - public bool ice_udp { get; set; } - [NoAccessorMethod] - [Version (since = "0.1.8")] - public bool keepalive_conncheck { get; set; } - [NoAccessorMethod] - public void* main_context { get; construct; } - [NoAccessorMethod] - public uint max_connectivity_checks { get; set; } - [NoAccessorMethod] - [Version (since = "0.0.4")] - public string proxy_ip { owned get; set; } - [NoAccessorMethod] - [Version (since = "0.0.4")] - public string proxy_password { owned get; set; } - [NoAccessorMethod] - [Version (since = "0.0.4")] - public uint proxy_port { get; set; } - [NoAccessorMethod] - [Version (since = "0.0.4")] - public uint proxy_type { get; set; } - [NoAccessorMethod] - [Version (since = "0.0.4")] - public string proxy_username { owned get; set; } - [NoAccessorMethod] - [Version (since = "0.0.11")] - public bool reliable { get; construct; } - [NoAccessorMethod] - [Version (since = "0.1.15")] - public uint stun_initial_timeout { get; set construct; } - [NoAccessorMethod] - [Version (since = "0.1.15")] - public uint stun_max_retransmissions { get; set construct; } - [NoAccessorMethod] - public uint stun_pacing_timer { get; set construct; } - [NoAccessorMethod] - [Version (since = "0.1.15")] - public uint stun_reliable_timeout { get; set construct; } - [NoAccessorMethod] - public string stun_server { owned get; set; } - [NoAccessorMethod] - public uint stun_server_port { get; set; } - [NoAccessorMethod] - public bool support_renomination { get; set; } - [NoAccessorMethod] - [Version (since = "0.0.7")] - public bool upnp { get; set construct; } - [NoAccessorMethod] - [Version (since = "0.0.7")] - public uint upnp_timeout { get; set construct; } - public signal void candidate_gathering_done (uint stream_id); - public signal void component_state_changed (uint stream_id, uint component_id, uint state); - public signal void initial_binding_request_received (uint stream_id); - [Version (deprecated = true, deprecated_since = "0.1.8")] - public signal void new_candidate (uint stream_id, uint component_id, string foundation); - [Version (since = "0.1.8")] - public signal void new_candidate_full (Nice.Candidate candidate); - [Version (deprecated = true, deprecated_since = "0.1.8")] - public signal void new_remote_candidate (uint stream_id, uint component_id, string foundation); - [Version (since = "0.1.8")] - public signal void new_remote_candidate_full (Nice.Candidate candidate); - [Version (deprecated = true, deprecated_since = "0.1.8")] - public signal void new_selected_pair (uint stream_id, uint component_id, string lfoundation, string rfoundation); - [Version (since = "0.1.8")] - public signal void new_selected_pair_full (uint stream_id, uint component_id, Nice.Candidate lcandidate, Nice.Candidate rcandidate); - [Version (since = "0.0.11")] - public signal void reliable_transport_writable (uint stream_id, uint component_id); - [Version (since = "0.1.5")] - public signal void streams_removed ([CCode (array_length = false, array_null_terminated = true)] uint[] stream_ids); - } - [CCode (cheader_filename = "nice.h", copy_function = "nice_candidate_copy", free_function = "nice_candidate_free")] - [Compact] - public class Candidate { - public Nice.Address addr; - public Nice.Address base_addr; - public uint component_id; - [CCode (array_length = false)] - public weak char foundation[33]; - public weak string password; - public uint32 priority; - public void* sockptr; - public uint stream_id; - public Nice.CandidateTransport transport; - public Nice.TurnServer turn; - public Nice.CandidateType type; - public weak string username; - [CCode (has_construct_function = false)] - public Candidate (Nice.CandidateType type); - public Nice.Candidate copy (); - [Version (since = "0.1.15")] - public bool equal_target (Nice.Candidate candidate2); - public void free (); - } - [CCode (cheader_filename = "nice.h", has_type_id = false)] - public struct Address { - [CCode (cname = "s.addr")] - public void* s_addr; - [CCode (cname = "s.ip4")] - public void* s_ip4; - [CCode (cname = "s.ip6")] - public void* s_ip6; - public void copy_to_sockaddr (void* sin); - public bool equal (Nice.Address b); - [Version (since = "0.1.8")] - public bool equal_no_port (Nice.Address b); - public void free (); - public uint get_port (); - public void init (); - public int ip_version (); - public bool is_private (); - public bool is_valid (); - public void set_from_sockaddr (void* sin); - public bool set_from_string (string str); - public void set_ipv4 (uint32 addr_ipv4); - public void set_ipv6 (uint8 addr_ipv6); - public void set_port (uint port); - public void to_string ([CCode (array_length = false, type = "gchar*")] char[] dst); - } - [CCode (cheader_filename = "nice.h", has_type_id = false)] - [Version (since = "0.1.5")] - public struct InputMessage { - [CCode (array_length_cname = "n_buffers")] - public weak GLib.InputVector[] buffers; - public int n_buffers; - public Nice.Address from; - public size_t length; - } - [CCode (cheader_filename = "nice.h", has_type_id = false)] - [Version (since = "0.1.5")] - public struct OutputMessage { - [CCode (array_length_cname = "n_buffers")] - public weak GLib.OutputVector[] buffers; - public int n_buffers; - } - [CCode (cheader_filename = "nice.h", cname = "TurnServer", has_type_id = false)] - public struct TurnServer { - public int ref_count; - public Nice.Address server; - public weak string username; - public weak string password; - public Nice.RelayType type; - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_AGENT_OPTION_", has_type_id = false)] - [Flags] - [Version (since = "0.1.15")] - public enum AgentOption { - REGULAR_NOMINATION, - RELIABLE, - LITE_MODE, - ICE_TRICKLE, - SUPPORT_RENOMINATION - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_CANDIDATE_TRANSPORT_", has_type_id = false)] - public enum CandidateTransport { - UDP, - TCP_ACTIVE, - TCP_PASSIVE, - TCP_SO - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_CANDIDATE_TYPE_", has_type_id = false)] - public enum CandidateType { - HOST, - SERVER_REFLEXIVE, - PEER_REFLEXIVE, - RELAYED - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_COMPATIBILITY_", has_type_id = false)] - public enum Compatibility { - RFC5245, - DRAFT19, - GOOGLE, - MSN, - WLM2009, - OC2007, - OC2007R2, - LAST - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_COMPONENT_STATE_", has_type_id = false)] - public enum ComponentState { - DISCONNECTED, - GATHERING, - CONNECTING, - CONNECTED, - READY, - FAILED, - LAST; - [Version (since = "0.1.6")] - public unowned string to_string (); - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_COMPONENT_TYPE_", has_type_id = false)] - public enum ComponentType { - RTP, - RTCP - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_NOMINATION_MODE_", has_type_id = false)] - [Version (since = "0.1.15")] - public enum NominationMode { - REGULAR, - AGGRESSIVE - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_PROXY_TYPE_", has_type_id = false)] - [Version (since = "0.0.4")] - public enum ProxyType { - NONE, - SOCKS5, - HTTP, - LAST - } - [CCode (cheader_filename = "nice.h", cname = "PseudoTcpDebugLevel", cprefix = "PSEUDO_TCP_DEBUG_", has_type_id = false)] - [Version (since = "0.0.11")] - public enum PseudoTcpDebugLevel { - NONE, - NORMAL, - VERBOSE - } - [CCode (cheader_filename = "nice.h", cname = "PseudoTcpShutdown", cprefix = "PSEUDO_TCP_SHUTDOWN_", has_type_id = false)] - [Version (since = "0.1.8")] - public enum PseudoTcpShutdown { - RD, - WR, - RDWR - } - [CCode (cheader_filename = "nice.h", cname = "PseudoTcpState", cprefix = "PSEUDO_TCP_", has_type_id = false)] - [Version (since = "0.0.11")] - public enum PseudoTcpState { - LISTEN, - SYN_SENT, - SYN_RECEIVED, - ESTABLISHED, - CLOSED, - FIN_WAIT_1, - FIN_WAIT_2, - CLOSING, - TIME_WAIT, - CLOSE_WAIT, - LAST_ACK - } - [CCode (cheader_filename = "nice.h", cname = "PseudoTcpWriteResult", cprefix = "WR_", has_type_id = false)] - [Version (since = "0.0.11")] - public enum PseudoTcpWriteResult { - SUCCESS, - TOO_LARGE, - FAIL - } - [CCode (cheader_filename = "nice.h", cprefix = "NICE_RELAY_TYPE_TURN_", has_type_id = false)] - public enum RelayType { - UDP, - TCP, - TLS - } - [CCode (cheader_filename = "nice.h", instance_pos = 4.9)] - public delegate void AgentRecvFunc (Nice.Agent agent, uint stream_id, uint component_id, [CCode (array_length_cname = "len", array_length_pos = 3.5, array_length_type = "guint", type = "gchar*")] uint8[] buf); - [CCode (cheader_filename = "nice.h", cname = "NICE_AGENT_MAX_REMOTE_CANDIDATES")] - public const int AGENT_MAX_REMOTE_CANDIDATES; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_DIRECTION_MS_PREF_ACTIVE")] - public const int CANDIDATE_DIRECTION_MS_PREF_ACTIVE; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_DIRECTION_MS_PREF_PASSIVE")] - public const int CANDIDATE_DIRECTION_MS_PREF_PASSIVE; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_MAX_FOUNDATION")] - public const int CANDIDATE_MAX_FOUNDATION; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TRANSPORT_MS_PREF_TCP")] - public const int CANDIDATE_TRANSPORT_MS_PREF_TCP; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TRANSPORT_MS_PREF_UDP")] - public const int CANDIDATE_TRANSPORT_MS_PREF_UDP; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_HOST")] - public const int CANDIDATE_TYPE_PREF_HOST; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_NAT_ASSISTED")] - public const int CANDIDATE_TYPE_PREF_NAT_ASSISTED; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_PEER_REFLEXIVE")] - public const int CANDIDATE_TYPE_PREF_PEER_REFLEXIVE; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_RELAYED")] - public const int CANDIDATE_TYPE_PREF_RELAYED; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_RELAYED_UDP")] - public const int CANDIDATE_TYPE_PREF_RELAYED_UDP; - [CCode (cheader_filename = "nice.h", cname = "NICE_CANDIDATE_TYPE_PREF_SERVER_REFLEXIVE")] - public const int CANDIDATE_TYPE_PREF_SERVER_REFLEXIVE; - [CCode (cheader_filename = "nice.h")] - public static void debug_disable (bool with_stun); - [CCode (cheader_filename = "nice.h")] - public static void debug_enable (bool with_stun); - [CCode (cheader_filename = "nice.h")] - public static string? interfaces_get_ip_for_interface (string interface_name); - [CCode (cheader_filename = "nice.h")] - public static GLib.List interfaces_get_local_interfaces (); - [CCode (cheader_filename = "nice.h")] - public static GLib.List interfaces_get_local_ips (bool include_loopback); - [CCode (cheader_filename = "nice.h", cname = "pseudo_tcp_set_debug_level")] - [Version (since = "0.0.11")] - public static void pseudo_tcp_set_debug_level (Nice.PseudoTcpDebugLevel level); -} diff --git a/plugins/meson.build b/plugins/meson.build index 8aa05215..3f804fcb 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -1,4 +1,3 @@ -subdir('ice') subdir('notification-sound') subdir('omemo') subdir('openpgp') diff --git a/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala b/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala index 97674f3f..9cfb4afc 100644 --- a/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala +++ b/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala @@ -25,6 +25,10 @@ public class Module : XmppStreamModule, Iq.Handler { private GetLocalIpAddresses? get_local_ip_addresses_impl = null; + public Module.with_local_ip_address_handler(owned GetLocalIpAddresses get_local_ip_addresses) { + set_local_ip_address_handler((owned) get_local_ip_addresses); + } + public override void attach(XmppStream stream) { stream.add_flag(new Flag()); query_availability.begin(stream); diff --git a/xmpp-vala/src/module/xep/0177_jingle_raw_udp.vala b/xmpp-vala/src/module/xep/0177_jingle_raw_udp.vala index 200cdfa9..b59c1b06 100644 --- a/xmpp-vala/src/module/xep/0177_jingle_raw_udp.vala +++ b/xmpp-vala/src/module/xep/0177_jingle_raw_udp.vala @@ -13,6 +13,10 @@ namespace Xmpp.Xep.JingleRawUdp { private GetLocalIpAddresses? get_local_ip_addresses_impl = null; + public Module.with_local_ip_address_handler(owned GetLocalIpAddresses get_local_ip_addresses) { + set_local_ip_address_handler((owned) get_local_ip_addresses); + } + public override void attach(XmppStream stream) { stream.get_module(Jingle.Module.IDENTITY).register_transport(this); stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI); -- cgit v1.3 From 630b1368331ef0034b343bd2f00b116c8cd90391 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sun, 4 Oct 2026 17:49:16 +0200 Subject: Fix some warnings --- .../omemo/ui/encryption_preferences_entry.vala | 4 + main/src/plugins/omemo/ui/manage_key_dialog.vala | 3 + main/src/ui/main_window.vala | 24 +++--- main/src/ui/util/data_forms.vala | 2 +- xmpp-vala/src/core/stanza_attribute.vala | 16 +++- xmpp-vala/src/core/stanza_node.vala | 92 ++++++++++++---------- xmpp-vala/src/core/stream_connect.vala | 10 ++- xmpp-vala/src/module/bookmarks_provider.vala | 8 +- xmpp-vala/src/module/iq/module.vala | 2 +- xmpp-vala/src/module/sasl.vala | 14 ++-- xmpp-vala/src/module/session.vala | 10 ++- xmpp-vala/src/module/xep/0004_data_forms.vala | 3 +- .../module/xep/0030_service_discovery/module.vala | 4 +- xmpp-vala/src/module/xep/0045_muc/module.vala | 24 +++--- xmpp-vala/src/module/xep/0048_bookmarks.vala | 10 +-- .../src/module/xep/0049_private_xml_storage.vala | 4 +- xmpp-vala/src/module/xep/0054_vcard/module.vala | 2 +- xmpp-vala/src/module/xep/0060_pubsub.vala | 10 +-- .../src/module/xep/0065_socks5_bytestreams.vala | 2 +- .../src/module/xep/0077_in_band_registration.vala | 6 +- .../src/module/xep/0082_date_time_profiles.vala | 4 +- xmpp-vala/src/module/xep/0084_user_avatars.vala | 2 +- .../src/module/xep/0166_jingle/component.vala | 12 ++- xmpp-vala/src/module/xep/0166_jingle/content.vala | 12 ++- .../src/module/xep/0166_jingle/jingle_flag.vala | 7 +- xmpp-vala/src/module/xep/0166_jingle/session.vala | 7 +- .../0176_jingle_ice_udp/transport_parameters.vala | 6 +- .../src/module/xep/0191_blocking_command.vala | 8 +- xmpp-vala/src/module/xep/0199_ping.vala | 2 +- .../xep/0215_external_service_discovery.vala | 2 +- .../src/module/xep/0234_jingle_file_transfer.vala | 2 +- .../module/xep/0260_jingle_socks5_bytestreams.vala | 10 ++- xmpp-vala/src/module/xep/0272_muji.vala | 7 +- xmpp-vala/src/module/xep/0280_message_carbons.vala | 12 ++- .../xep/0313_2_message_archive_management.vala | 4 +- .../xep/0313_message_archive_management.vala | 2 +- .../module/xep/0392_consistent_color/hsluv.vala | 6 +- xmpp-vala/src/module/xep/0402_bookmarks2.vala | 6 +- xmpp-vala/src/module/xep/0461_replies.vala | 1 - xmpp-vala/tests/color.vala | 6 +- xmpp-vala/tests/stanza.vala | 48 ++++++----- xmpp-vala/tests/testcase.vala | 13 ++- 42 files changed, 271 insertions(+), 158 deletions(-) (limited to 'xmpp-vala/src/module') diff --git a/main/src/plugins/omemo/ui/encryption_preferences_entry.vala b/main/src/plugins/omemo/ui/encryption_preferences_entry.vala index 55faecac..7f53a1b2 100644 --- a/main/src/plugins/omemo/ui/encryption_preferences_entry.vala +++ b/main/src/plugins/omemo/ui/encryption_preferences_entry.vala @@ -224,6 +224,10 @@ public class OmemoPreferencesWidget : Adw.PreferencesGroup { case TrustLevel.VERIFIED: trust_str = _("Verified"); break; + case TrustLevel.TRUSTED: + case TrustLevel.UNKNOWN: + default: + break; } action_row.add_suffix(new Label(trust_str)); diff --git a/main/src/plugins/omemo/ui/manage_key_dialog.vala b/main/src/plugins/omemo/ui/manage_key_dialog.vala index 65033999..59e6db24 100644 --- a/main/src/plugins/omemo/ui/manage_key_dialog.vala +++ b/main/src/plugins/omemo/ui/manage_key_dialog.vala @@ -141,6 +141,9 @@ public class ManageKeyDialog : Gtk.Dialog { main_desc_label.set_markup(_("This key is currently %s.").printf(""+_("rejected")+"")+" "+_("This means it cannot be used by %s to decipher your messages, and you won't see messages encrypted with it.").printf(@"$(device[db.identity_meta.address_name])")); main_action_list.append(accept_row); break; + case TrustLevel.UNKNOWN: + default: + break; } //Row clicked - go to appropriate screen diff --git a/main/src/ui/main_window.vala b/main/src/ui/main_window.vala index d2a23954..da6960ea 100644 --- a/main/src/ui/main_window.vala +++ b/main/src/ui/main_window.vala @@ -11,21 +11,21 @@ public class MainWindow : Adw.ApplicationWindow { public signal void conversation_selected(Conversation conversation); - [GtkChild] public Stack stack; - [GtkChild] public Adw.NavigationSplitView navigation_split_view; + [GtkChild] public unowned Stack stack; + [GtkChild] public unowned Adw.NavigationSplitView navigation_split_view; - [GtkChild] public MenuButton add_button; - [GtkChild] public MenuButton menu_button; + [GtkChild] public unowned MenuButton add_button; + [GtkChild] public unowned MenuButton menu_button; - [GtkChild] public Adw.HeaderBar conversation_headerbar; - [GtkChild] public Adw.WindowTitle conversation_window_title; + [GtkChild] public unowned Adw.HeaderBar conversation_headerbar; + [GtkChild] public unowned Adw.WindowTitle conversation_window_title; - [GtkChild] public ConversationView conversation_view; - [GtkChild] public ConversationSelector conversation_selector; - [GtkChild] public Adw.Flap search_flap; - [GtkChild] private Stack left_stack; - [GtkChild] private Stack right_stack; - [GtkChild] public Adw.Bin search_frame; + [GtkChild] public unowned ConversationView conversation_view; + [GtkChild] public unowned ConversationSelector conversation_selector; + [GtkChild] public unowned Adw.Flap search_flap; + [GtkChild] private unowned Stack left_stack; + [GtkChild] private unowned Stack right_stack; + [GtkChild] public unowned Adw.Bin search_frame; public GlobalSearch global_search; diff --git a/main/src/ui/util/data_forms.vala b/main/src/ui/util/data_forms.vala index 7fb9b87d..0b91da15 100644 --- a/main/src/ui/util/data_forms.vala +++ b/main/src/ui/util/data_forms.vala @@ -18,7 +18,7 @@ namespace Dino.Ui.Util { } public static ViewModel.PreferencesRow.Any? get_data_form_field_view_model(DataForms.DataForm.Field field) { - if (field.type_ == null) return null; + if (field.type_ == DataForms.DataForm.Type.UNKNOWN) return null; ViewModel.PreferencesRow.Any? view_model = null; diff --git a/xmpp-vala/src/core/stanza_attribute.vala b/xmpp-vala/src/core/stanza_attribute.vala index 6c6ac579..ba1616a5 100644 --- a/xmpp-vala/src/core/stanza_attribute.vala +++ b/xmpp-vala/src/core/stanza_attribute.vala @@ -56,7 +56,13 @@ public class StanzaAttribute : StanzaEntry { if (ns_uri == state.current_ns_uri || (ns_uri == XMLNS_URI && name == "xmlns")) { return printf(ATTRIBUTE_XML_NO_NS_FORMAT, true); } else { - return printf(ATTRIBUTE_XML_FORMAT, false, state.find_name((!)ns_uri)); + string ns_name = "_"; + try { + ns_name = state.find_name((!)ns_uri); + } catch (IOError e) { + warning("Error finding name: %s", e.message); + } + return printf(ATTRIBUTE_XML_FORMAT, false, ns_name); } } @@ -65,7 +71,13 @@ public class StanzaAttribute : StanzaEntry { if (ns_uri == state.current_ns_uri || (ns_uri == XMLNS_URI && name == "xmlns")) { return printf(ATTRIBUTE_XML_ANSI_NO_NS_FORMAT, true); } else { - return printf(ATTRIBUTE_XML_ANSI_FORMAT, false, state.find_name((!)ns_uri)); + string ns_name = "_"; + try { + ns_name = state.find_name((!)ns_uri); + } catch (IOError e) { + warning("Error finding name: %s", e.message); + } + return printf(ATTRIBUTE_XML_ANSI_FORMAT, false, ns_name); } } } diff --git a/xmpp-vala/src/core/stanza_node.vala b/xmpp-vala/src/core/stanza_node.vala index f44657f1..7a68da62 100644 --- a/xmpp-vala/src/core/stanza_node.vala +++ b/xmpp-vala/src/core/stanza_node.vala @@ -18,54 +18,62 @@ public abstract class StanzaEntry { public string? encoded_val { owned get { if (val == null) return null; - return ENCODABLE_VALUE_CHARS.replace_eval(val, -1, 0, 0, (match_info, result_builder) => { - int start; - match_info.fetch_pos(0, out start, null); - unowned string src = match_info.get_string(); - switch (src[start]) { - case '&': result_builder.append("&"); break; - case '"': result_builder.append("""); break; - case '\'': result_builder.append("'"); break; - case '<': result_builder.append("<"); break; - case '>': result_builder.append(">"); break; - default: error("Unreachable"); break; - } - return false; - }); + try { + return ENCODABLE_VALUE_CHARS.replace_eval(val, -1, 0, 0, (match_info, result_builder) => { + int start; + match_info.fetch_pos(0, out start, null); + unowned string src = match_info.get_string(); + switch (src[start]) { + case '&': result_builder.append("&"); break; + case '"': result_builder.append("""); break; + case '\'': result_builder.append("'"); break; + case '<': result_builder.append("<"); break; + case '>': result_builder.append(">"); break; + default: error("Unreachable"); break; + } + return false; + }); + } catch (RegexError e) { + error("Error encoding entities in string \"%s\": %s", val, e.message); + } } set { if (value == null) { val = null; return; } - val = DECODABLE_VALUE_SEQUENCES.replace_eval(value, -1, 0, 0, (match_info, result_builder) => { - int start, end; - match_info.fetch_pos(0, out start, out end); - unowned string src = match_info.get_string(); - switch (src[start+1]) { - case 'g': result_builder.append_c('>'); break; - case 'l': result_builder.append_c('<'); break; - case 'q': result_builder.append_c('"'); break; - case 'a': - switch (src[start+2]) { - case 'p': result_builder.append_c('\''); break; - case 'm': result_builder.append_c('&'); break; - default: critical("Invalid encoding: %s in %s", match_info.fetch(0), src); break; - } - break; - case '#': - unichar num = -1; - if (src[start+2] == 'x') { - src.substring(start+3, start-end-3).scanf("%x", &num); - } else { - num = int.parse(src.substring(start+2, start-end-2)); - } - result_builder.append_unichar(num); - break; - default: critical("Invalid encoding: %s in %s", match_info.fetch(0), src); break; - } - return false; - }); + try { + val = DECODABLE_VALUE_SEQUENCES.replace_eval(value, -1, 0, 0, (match_info, result_builder) => { + int start, end; + match_info.fetch_pos(0, out start, out end); + unowned string src = match_info.get_string(); + switch (src[start + 1]) { + case 'g': result_builder.append_c('>'); break; + case 'l': result_builder.append_c('<'); break; + case 'q': result_builder.append_c('"'); break; + case 'a': + switch (src[start + 2]) { + case 'p': result_builder.append_c('\''); break; + case 'm': result_builder.append_c('&'); break; + default: critical("Invalid encoding: %s in %s", match_info.fetch(0), src); break; + } + break; + case '#': + unichar num = -1; + if (src[start + 2] == 'x') { + src.substring(start + 3, start - end - 3).scanf("%x", &num); + } else { + num = int.parse(src.substring(start + 2, start - end - 2)); + } + result_builder.append_unichar(num); + break; + default: critical("Invalid encoding: %s in %s", match_info.fetch(0), src); break; + } + return false; + }); + } catch (RegexError e) { + error("Error decoding entities in string \"%s\": %s", value, e.message); + } } } diff --git a/xmpp-vala/src/core/stream_connect.vala b/xmpp-vala/src/core/stream_connect.vala index 7e3843fa..a496fc3c 100644 --- a/xmpp-vala/src/core/stream_connect.vala +++ b/xmpp-vala/src/core/stream_connect.vala @@ -15,7 +15,7 @@ namespace Xmpp { public async XmppStreamResult establish_stream(Jid bare_jid, Gee.List 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); + TlsXmppStream.OnInvalidCertWrapper on_invalid_cert_wrapper = new TlsXmppStream.OnInvalidCertWrapper((owned) on_invalid_cert); //Lookup xmpp-client and xmpps-client SRV records GLib.List? targets = new GLib.List(); @@ -72,7 +72,13 @@ namespace Xmpp { connection_timeout_id = Timeout.add_seconds(30, () => { warning("Connection attempt timed out"); - stream.disconnect(); + stream.disconnect.begin((_, res) => { + try { + stream.disconnect.end(res); + } catch (IOError e) { + debug("Error while disconnecting: %s", e.message); + } + }); connection_timeout_id = 0; return Source.REMOVE; }); diff --git a/xmpp-vala/src/module/bookmarks_provider.vala b/xmpp-vala/src/module/bookmarks_provider.vala index 6ddcc5af..458ff183 100644 --- a/xmpp-vala/src/module/bookmarks_provider.vala +++ b/xmpp-vala/src/module/bookmarks_provider.vala @@ -8,10 +8,10 @@ public interface BookmarksProvider : Object { public signal void conference_changed(XmppStream stream, Conference conferences); public signal void received_conferences(XmppStream stream, Set conferences); - public async abstract async Set? get_conferences(XmppStream stream); - public async abstract void add_conference(XmppStream stream, Conference conference); - public async abstract void remove_conference(XmppStream stream, Conference conference); - public async abstract void replace_conference(XmppStream stream, Jid muc_jid, Conference modified_conference); + public async abstract async Set? get_conferences(XmppStream stream) throws IOError; + public async abstract void add_conference(XmppStream stream, Conference conference) throws IOError; + public async abstract void remove_conference(XmppStream stream, Conference conference) throws IOError; + public async abstract void replace_conference(XmppStream stream, Jid muc_jid, Conference modified_conference) throws IOError; } } diff --git a/xmpp-vala/src/module/iq/module.vala b/xmpp-vala/src/module/iq/module.vala index bb9260c9..917f6660 100644 --- a/xmpp-vala/src/module/iq/module.vala +++ b/xmpp-vala/src/module/iq/module.vala @@ -23,7 +23,7 @@ namespace Xmpp.Iq { Idle.add(send_iq_async.callback); } }); - stream.write_async(iq.stanza, io_priority, cancellable); + yield stream.write_async(iq.stanza, io_priority, cancellable); ulong cancelled_handler_id = 0; if (cancellable != null) { cancelled_handler_id = cancellable.cancelled.connect(() => Idle.add(send_iq_async.callback)); diff --git a/xmpp-vala/src/module/sasl.vala b/xmpp-vala/src/module/sasl.vala index 035cc723..f0c2d6ed 100644 --- a/xmpp-vala/src/module/sasl.vala +++ b/xmpp-vala/src/module/sasl.vala @@ -73,10 +73,14 @@ namespace Xmpp.Sasl { } else if (node.name == "challenge" && stream.has_flag(Flag.IDENTITY)) { Flag flag = stream.get_flag(Flag.IDENTITY); if (flag.mechanism == Mechanism.SCRAM_SHA_1) { - var challenge_response = compute_challenge_response(node.get_string_content(), flag.password, flag.client_nonce, flag.name); - flag.server_signature = challenge_response.expected_server_signature; - stream.write(new StanzaNode.build("response", NS_URI).add_self_xmlns() - .put_node(new StanzaNode.text(Base64.encode((uchar[]) (challenge_response.response).to_utf8())))); + try { + var challenge_response = compute_challenge_response(node.get_string_content(), flag.password, flag.client_nonce, flag.name); + flag.server_signature = challenge_response.expected_server_signature; + stream.write(new StanzaNode.build("response", NS_URI).add_self_xmlns() + .put_node(new StanzaNode.text(Base64.encode((uchar[]) (challenge_response.response).to_utf8())))); + } catch (Error e) { + warning("Failed processing challenge: %s", e.message); + } } } } @@ -165,7 +169,7 @@ namespace Xmpp.Sasl { public string response { get; set; } } - public static ChallengeResponse compute_challenge_response(string challenge, string password, string client_nonce, string name) { + public static ChallengeResponse compute_challenge_response(string challenge, string password, string client_nonce, string name) throws Error { string challenge_base64 = (string) Base64.decode(challenge); string? server_nonce = null; uint8[] salt = null; diff --git a/xmpp-vala/src/module/session.vala b/xmpp-vala/src/module/session.vala index b1436d1e..fa947624 100644 --- a/xmpp-vala/src/module/session.vala +++ b/xmpp-vala/src/module/session.vala @@ -28,9 +28,13 @@ public class Module : XmppStreamNegotiationModule { stream.add_flag(new Flag()); Iq.Stanza iq = new Iq.Stanza.set(new StanzaNode.build("session", NS_URI).add_self_xmlns()) { to=stream.remote_name }; - Iq.Stanza result_iq = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); - if (!result_iq.is_error()) { - stream.get_flag(Flag.IDENTITY).finished = true; + try { + Iq.Stanza result_iq = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + if (!result_iq.is_error()) { + stream.get_flag(Flag.IDENTITY).finished = true; + } + } catch (IOError e) { + warning("Error establishing legacy session: %s", e.message); } } } diff --git a/xmpp-vala/src/module/xep/0004_data_forms.vala b/xmpp-vala/src/module/xep/0004_data_forms.vala index 6b5624da..f481e174 100644 --- a/xmpp-vala/src/module/xep/0004_data_forms.vala +++ b/xmpp-vala/src/module/xep/0004_data_forms.vala @@ -18,6 +18,7 @@ public class DataForm { } public enum Type { + UNKNOWN, BOOLEAN, FIXED, HIDDEN, @@ -44,7 +45,7 @@ public class DataForm { get { return node.get_attribute("label", NS_URI); } set { node.set_attribute("label", value); } } - public virtual Type? type_ { get; internal set; default=null; } + public virtual Type type_ { get; internal set; default=Type.UNKNOWN; } public string? var { get { return node.get_attribute("var", NS_URI); } set { node.set_attribute("var", value); } diff --git a/xmpp-vala/src/module/xep/0030_service_discovery/module.vala b/xmpp-vala/src/module/xep/0030_service_discovery/module.vala index 537e460b..1ba8ac3a 100644 --- a/xmpp-vala/src/module/xep/0030_service_discovery/module.vala +++ b/xmpp-vala/src/module/xep/0030_service_discovery/module.vala @@ -45,7 +45,7 @@ public class Module : XmppStreamModule, Iq.Handler { return yield this.cache.get_entity_identities(jid); } - public async InfoResult? request_info(XmppStream stream, Jid jid) { + public async InfoResult? request_info(XmppStream stream, Jid jid) throws IOError { var future = active_info_requests[jid]; if (future == null) { var promise = new Promise(); @@ -69,7 +69,7 @@ public class Module : XmppStreamModule, Iq.Handler { } } - public async ItemsResult? request_items(XmppStream stream, Jid jid) { + public async ItemsResult? request_items(XmppStream stream, Jid jid) throws IOError { StanzaNode query_node = new StanzaNode.build("query", NS_URI_ITEMS).add_self_xmlns(); Iq.Stanza iq = new Iq.Stanza.get(query_node) { to=jid }; diff --git a/xmpp-vala/src/module/xep/0045_muc/module.vala b/xmpp-vala/src/module/xep/0045_muc/module.vala index 76045172..e4c066f0 100644 --- a/xmpp-vala/src/module/xep/0045_muc/module.vala +++ b/xmpp-vala/src/module/xep/0045_muc/module.vala @@ -215,7 +215,7 @@ public class Module : XmppStreamModule { stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq); } - public async void change_affiliation(XmppStream stream, Jid muc_jid, Jid? user_jid, string? nick, string new_affiliation) { + public async void change_affiliation(XmppStream stream, Jid muc_jid, Jid? user_jid, string? nick, string new_affiliation) throws IOError { StanzaNode item_node = new StanzaNode.build("item", NS_URI_ADMIN) .put_attribute("affiliation", new_affiliation, NS_URI_ADMIN); if (user_jid != null) { @@ -229,7 +229,7 @@ public class Module : XmppStreamModule { yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); } - public async DataForms.DataForm? get_config_form(XmppStream stream, Jid jid) { + public async DataForms.DataForm? get_config_form(XmppStream stream, Jid jid) throws IOError { Iq.Stanza get_iq = new Iq.Stanza.get(new StanzaNode.build("query", NS_URI_OWNER).add_self_xmlns()) { to=jid }; Iq.Stanza result_iq = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, get_iq); @@ -241,7 +241,7 @@ public class Module : XmppStreamModule { return null; } - public async void set_config_form(XmppStream stream, Jid jid, DataForms.DataForm data_form) { + public async void set_config_form(XmppStream stream, Jid jid, DataForms.DataForm data_form) throws IOError { StanzaNode stanza_node = new StanzaNode.build("query", NS_URI_OWNER); stanza_node.add_self_xmlns().put_node(data_form.get_submit_node()); Iq.Stanza set_iq = new Iq.Stanza.set(stanza_node) { to=jid }; @@ -420,7 +420,7 @@ public class Module : XmppStreamModule { yield query_affiliation(stream, muc_jid, "owner"); } - private async Gee.List? query_affiliation(XmppStream stream, Jid jid, string affiliation) { + private async Gee.List? query_affiliation(XmppStream stream, Jid jid, string affiliation) throws IOError { Iq.Stanza iq = new Iq.Stanza.get( new StanzaNode.build("query", NS_URI_ADMIN) .add_self_xmlns() @@ -538,14 +538,18 @@ public class ReceivedPipelineListener : StanzaListener { if (item_nodes.size > 0) { var affiliations = new HashMap(); foreach (StanzaNode item_node in item_nodes) { - string jid_str = item_node.get_attribute("jid", Muc.NS_URI_USER); - Jid real_jid = Jid.from_string(jid_str); - string affiliation_str = item_node.get_attribute("affiliation", Muc.NS_URI_USER); - Muc.Affiliation affiliation = Muc.Module.parse_affiliation(affiliation_str); + try { + string jid_str = item_node.get_attribute("jid", Muc.NS_URI_USER); + Jid real_jid = Jid.from_string(jid_str); + string affiliation_str = item_node.get_attribute("affiliation", Muc.NS_URI_USER); + Muc.Affiliation affiliation = Muc.Module.parse_affiliation(affiliation_str); - affiliations[real_jid] = affiliation; + affiliations[real_jid] = affiliation; - stream.get_flag(Flag.IDENTITY).set_offline_member(message.from, real_jid, affiliation); + stream.get_flag(Flag.IDENTITY).set_offline_member(message.from, real_jid, affiliation); + } catch (InvalidJidError e) { + warning("Received invalid affiliation update: %s", e.message); + } } string? mav_since = MucAffiliationsVersioning.get_mav_since(x_node); diff --git a/xmpp-vala/src/module/xep/0048_bookmarks.vala b/xmpp-vala/src/module/xep/0048_bookmarks.vala index 46814e4a..dc009a1e 100644 --- a/xmpp-vala/src/module/xep/0048_bookmarks.vala +++ b/xmpp-vala/src/module/xep/0048_bookmarks.vala @@ -6,7 +6,7 @@ private const string NS_URI = "storage:bookmarks"; public class Module : BookmarksProvider, XmppStreamModule { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0048_bookmarks_module"); - public async Set? get_conferences(XmppStream stream) { + public async Set? get_conferences(XmppStream stream) throws IOError { StanzaNode get_node = new StanzaNode.build("storage", NS_URI).add_self_xmlns(); StanzaNode? result_node = yield stream.get_module(PrivateXmlStorage.Module.IDENTITY).retrieve(stream, get_node); if (result_node == null) return null; @@ -20,7 +20,7 @@ public class Module : BookmarksProvider, XmppStreamModule { return ret; } - private async void set_conferences(XmppStream stream, Set conferences) { + private async void set_conferences(XmppStream stream, Set conferences) throws IOError { StanzaNode storage_node = (new StanzaNode.build("storage", NS_URI)).add_self_xmlns(); foreach (Conference conference in conferences) { Bookmarks1Conference? bookmarks1conference = conference as Bookmarks1Conference; @@ -45,13 +45,13 @@ public class Module : BookmarksProvider, XmppStreamModule { stream.get_module(Module.IDENTITY).received_conferences(stream, conferences); } - public async void add_conference(XmppStream stream, Conference conference) { + public async void add_conference(XmppStream stream, Conference conference) throws IOError { Set? conferences = yield get_conferences(stream); conferences.add(conference); yield set_conferences(stream, conferences); } - public async void replace_conference(XmppStream stream, Jid muc_jid, Conference modified_conference) { + public async void replace_conference(XmppStream stream, Jid muc_jid, Conference modified_conference) throws IOError { Set? conferences = yield get_conferences(stream); foreach (Conference conference in conferences) { if (conference.jid.equals(muc_jid)) { @@ -64,7 +64,7 @@ public class Module : BookmarksProvider, XmppStreamModule { yield set_conferences(stream, conferences); } - public async void remove_conference(XmppStream stream, Conference conference_remove) { + public async void remove_conference(XmppStream stream, Conference conference_remove) throws IOError { Set? conferences = yield get_conferences(stream); conferences.remove(conference_remove); yield set_conferences(stream, conferences); diff --git a/xmpp-vala/src/module/xep/0049_private_xml_storage.vala b/xmpp-vala/src/module/xep/0049_private_xml_storage.vala index 81ccde9b..a6501505 100644 --- a/xmpp-vala/src/module/xep/0049_private_xml_storage.vala +++ b/xmpp-vala/src/module/xep/0049_private_xml_storage.vala @@ -6,13 +6,13 @@ namespace Xmpp.Xep.PrivateXmlStorage { public class Module : XmppStreamModule { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0049_private_xml_storage"); - public async void store(XmppStream stream, StanzaNode node) { + public async void store(XmppStream stream, StanzaNode node) throws IOError { StanzaNode queryNode = new StanzaNode.build("query", NS_URI).add_self_xmlns().put_node(node); Iq.Stanza iq = new Iq.Stanza.set(queryNode); yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); } - public async StanzaNode? retrieve(XmppStream stream, StanzaNode node) { + public async StanzaNode? retrieve(XmppStream stream, StanzaNode node) throws IOError { StanzaNode queryNode = new StanzaNode.build("query", NS_URI).add_self_xmlns().put_node(node); Iq.Stanza iq = new Iq.Stanza.get(queryNode); Iq.Stanza iq_result = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); diff --git a/xmpp-vala/src/module/xep/0054_vcard/module.vala b/xmpp-vala/src/module/xep/0054_vcard/module.vala index 4df1d9a5..4c02a2d1 100644 --- a/xmpp-vala/src/module/xep/0054_vcard/module.vala +++ b/xmpp-vala/src/module/xep/0054_vcard/module.vala @@ -2,7 +2,7 @@ namespace Xmpp.Xep.VCard { private const string NS_URI = "vcard-temp"; private const string NS_URI_UPDATE = NS_URI + ":x:update"; -public async Bytes? fetch_image(XmppStream stream, Jid jid, string hash) { +public async Bytes? fetch_image(XmppStream stream, Jid jid, string hash) throws IOError { Iq.Stanza iq = new Iq.Stanza.get(new StanzaNode.build("vCard", NS_URI).add_self_xmlns()) { to=jid }; Iq.Stanza iq_res = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); diff --git a/xmpp-vala/src/module/xep/0060_pubsub.vala b/xmpp-vala/src/module/xep/0060_pubsub.vala index c9af4263..88b9cd31 100644 --- a/xmpp-vala/src/module/xep/0060_pubsub.vala +++ b/xmpp-vala/src/module/xep/0060_pubsub.vala @@ -41,7 +41,7 @@ namespace Xmpp.Xep.Pubsub { retract_listeners.unset(node); } - public async Gee.List? request_all(XmppStream stream, Jid? jid, string node) { // TODO multiple nodes gehen auch + public async Gee.List? request_all(XmppStream stream, Jid? jid, string node) throws IOError { // TODO multiple nodes gehen auch Iq.Stanza request_iq = new Iq.Stanza.get(new StanzaNode.build("pubsub", NS_URI).add_self_xmlns().put_node(new StanzaNode.build("items", NS_URI).put_attribute("node", node))); if (jid != null) request_iq.to = jid; @@ -72,7 +72,7 @@ namespace Xmpp.Xep.Pubsub { XmppStream stream, Jid? jid, string node_id, string? item_id, StanzaNode content, PublishOptions? publish_options = null, bool try_reconfiguring = true - ) { + ) throws IOError { StanzaNode pubsub_node = new StanzaNode.build("pubsub", NS_URI).add_self_xmlns(); StanzaNode publish_node = new StanzaNode.build("publish", NS_URI).put_attribute("node", node_id); pubsub_node.put_node(publish_node); @@ -142,7 +142,7 @@ namespace Xmpp.Xep.Pubsub { stream.get_module(Iq.Module.IDENTITY).send_iq(stream, iq, null); } - public async DataForms.DataForm? request_node_config(XmppStream stream, Jid? jid, string node_id) { + public async DataForms.DataForm? request_node_config(XmppStream stream, Jid? jid, string node_id) throws IOError { StanzaNode pubsub_node = new StanzaNode.build("pubsub", NS_URI_OWNER).add_self_xmlns(); StanzaNode publish_node = new StanzaNode.build("configure", NS_URI_OWNER).put_attribute("node", node_id); pubsub_node.put_node(publish_node); @@ -154,7 +154,7 @@ namespace Xmpp.Xep.Pubsub { return DataForms.DataForm.create_from_node(data_form_node); } - public async bool submit_node_config(XmppStream stream, DataForms.DataForm data_form, string node_id) { + public async bool submit_node_config(XmppStream stream, DataForms.DataForm data_form, string node_id) throws IOError { StanzaNode submit_node = data_form.get_submit_node(); StanzaNode pubsub_node = new StanzaNode.build("pubsub", Pubsub.NS_URI_OWNER).add_self_xmlns(); @@ -222,7 +222,7 @@ namespace Xmpp.Xep.Pubsub { } } - private async bool change_node_config(XmppStream stream, Jid jid, string node, PublishOptions publish_options) { + private async bool change_node_config(XmppStream stream, Jid jid, string node, PublishOptions publish_options) throws IOError { DataForms.DataForm? data_form = yield stream.get_module(Pubsub.Module.IDENTITY).request_node_config(stream, jid, node); if (data_form == null) return false; diff --git a/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala b/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala index 9cfb4afc..4bb46837 100644 --- a/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala +++ b/xmpp-vala/src/module/xep/0065_socks5_bytestreams.vala @@ -50,7 +50,7 @@ public class Module : XmppStreamModule, Iq.Handler { return get_local_ip_addresses_impl(); } - private async void query_availability(XmppStream stream) { + private async void query_availability(XmppStream stream) throws IOError { ServiceDiscovery.ItemsResult? items_result = yield stream.get_module(ServiceDiscovery.Module.IDENTITY).request_items(stream, stream.remote_name); if (items_result == null) return; diff --git a/xmpp-vala/src/module/xep/0077_in_band_registration.vala b/xmpp-vala/src/module/xep/0077_in_band_registration.vala index 12ed2f1c..0d2dae40 100644 --- a/xmpp-vala/src/module/xep/0077_in_band_registration.vala +++ b/xmpp-vala/src/module/xep/0077_in_band_registration.vala @@ -7,7 +7,7 @@ public const string NS_URI = "jabber:iq:register"; public class Module : XmppStreamNegotiationModule { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0077_in_band_registration"); - public async Form? get_from_server(XmppStream stream, Jid jid) { + public async Form? get_from_server(XmppStream stream, Jid jid) throws IOError { StanzaNode query_node = new StanzaNode.build("query", NS_URI).add_self_xmlns(); Iq.Stanza request_form_iq = new Iq.Stanza.get(query_node) { to=jid }; request_form_iq.to = jid; @@ -16,7 +16,7 @@ public class Module : XmppStreamNegotiationModule { return new Form.from_node(stream, iq_result); } - public async string? submit_to_server(XmppStream stream, Jid jid, Form form) { + public async string? submit_to_server(XmppStream stream, Jid jid, Form form) throws IOError { StanzaNode query_node = new StanzaNode.build("query", NS_URI).add_self_xmlns(); query_node.put_node(form.get_submit_node()); Iq.Stanza iq = new Iq.Stanza.set(query_node) { to=jid }; @@ -30,7 +30,7 @@ public class Module : XmppStreamNegotiationModule { return null; } - public async ErrorStanza? change_password(XmppStream stream, Jid bare_jid, string new_pw) { + public async ErrorStanza? change_password(XmppStream stream, Jid bare_jid, string new_pw) throws IOError { StanzaNode pw_change_node = new StanzaNode.build("query", NS_URI).add_self_xmlns(); StanzaNode username_node = new StanzaNode.build("username", NS_URI); StanzaNode pw_node = new StanzaNode.build("password", NS_URI); diff --git a/xmpp-vala/src/module/xep/0082_date_time_profiles.vala b/xmpp-vala/src/module/xep/0082_date_time_profiles.vala index 3237208e..8cd3cfb1 100644 --- a/xmpp-vala/src/module/xep/0082_date_time_profiles.vala +++ b/xmpp-vala/src/module/xep/0082_date_time_profiles.vala @@ -15,8 +15,8 @@ public TimeZone? parse_tzd(string tzd) { } else { return null; } - int h_offset = unprefixed.substring(0, 2).to_int(); - int m_offset = unprefixed.substring(3, 2).to_int(); + int h_offset = int.parse(unprefixed.substring(0, 2)); + int m_offset = int.parse(unprefixed.substring(3, 2)); int offset = h_offset * 60 * 60 + m_offset * 60; if (tzd.has_prefix("-")) { offset = -offset; diff --git a/xmpp-vala/src/module/xep/0084_user_avatars.vala b/xmpp-vala/src/module/xep/0084_user_avatars.vala index 680c8e78..76ad824b 100644 --- a/xmpp-vala/src/module/xep/0084_user_avatars.vala +++ b/xmpp-vala/src/module/xep/0084_user_avatars.vala @@ -25,7 +25,7 @@ namespace Xmpp.Xep.UserAvatars { stream.get_module(Pubsub.Module.IDENTITY).delete_node(stream, null, NS_URI_METADATA); } - public async Bytes? fetch_image(XmppStream stream, Jid jid, string hash) { + public async Bytes? fetch_image(XmppStream stream, Jid jid, string hash) throws IOError { Gee.List? items = yield stream.get_module(Pubsub.Module.IDENTITY).request_all(stream, jid, NS_URI_DATA); if (items == null || items.size == 0 || items[0].sub_nodes.size == 0) return null; diff --git a/xmpp-vala/src/module/xep/0166_jingle/component.vala b/xmpp-vala/src/module/xep/0166_jingle/component.vala index e30175d5..f08ffbce 100644 --- a/xmpp-vala/src/module/xep/0166_jingle/component.vala +++ b/xmpp-vala/src/module/xep/0166_jingle/component.vala @@ -41,7 +41,11 @@ namespace Xmpp.Xep.Jingle { assert(!this.stream.ready); promise.set_value(stream); if (terminated != null) { - yield stream.close_async(); + try { + yield stream.close_async(); + } catch (IOError e) { + warning("Failed closing stream provided for terminated connection: %s", e.message); + } } } @@ -53,7 +57,11 @@ namespace Xmpp.Xep.Jingle { if (terminated == null) { terminated = (reason_name ?? "") + " - " + (reason_text ?? "") + @"we terminated? $we_terminated"; if (stream.ready) { - yield stream.value.close_async(); + try { + yield stream.value.close_async(); + } catch (IOError e) { + warning("Failed closing stream when terminating connection: %s", e.message); + } } else { promise.set_exception(new IOError.FAILED("Jingle connection failed")); } diff --git a/xmpp-vala/src/module/xep/0166_jingle/content.vala b/xmpp-vala/src/module/xep/0166_jingle/content.vala index f6af1b17..07cadc36 100644 --- a/xmpp-vala/src/module/xep/0166_jingle/content.vala +++ b/xmpp-vala/src/module/xep/0166_jingle/content.vala @@ -67,7 +67,7 @@ public class Xmpp.Xep.Jingle.Content : Object { ContentType content_type, ContentParameters content_params, Transport transport, TransportParameters? transport_params, SecurityPrecondition? security_precondition, SecurityParameters? security_params, - Jid local_full_jid, Jid peer_full_jid) throws Error { + Jid local_full_jid, Jid peer_full_jid) { this.content_name = content_name; this.senders = senders; this.role = Role.RESPONDER; @@ -142,7 +142,7 @@ public class Xmpp.Xep.Jingle.Content : Object { this.content_params.accept(stream, session, this); } - internal void handle_accept(XmppStream stream, ContentNode content_node) { + internal void handle_accept(XmppStream stream, ContentNode content_node) throws IqError { this.transport_params.handle_transport_accept(content_node.transport); this.transport_params.create_transport_connection(stream, this); this.content_params.handle_accept(stream, this.session, this, content_node.description); @@ -157,7 +157,13 @@ public class Xmpp.Xep.Jingle.Content : Object { return; } tried_transport_methods.add(new_transport.ns_uri); - transport_params = new_transport.create_transport_parameters(stream, transport_params.components, local_full_jid, peer_full_jid); + try { + transport_params = new_transport.create_transport_parameters(stream, transport_params.components, local_full_jid, peer_full_jid); + } catch (Error e) { + session.terminate(ReasonElement.FAILED_TRANSPORT, null, e.message); + // TODO should we only terminate this content or really the whole session? + return; + } set_transport_params(transport_params); session.send_transport_replace(this, transport_params); state = State.REPLACING_TRANSPORT; diff --git a/xmpp-vala/src/module/xep/0166_jingle/jingle_flag.vala b/xmpp-vala/src/module/xep/0166_jingle/jingle_flag.vala index 9f0acd27..f451f4c9 100644 --- a/xmpp-vala/src/module/xep/0166_jingle/jingle_flag.vala +++ b/xmpp-vala/src/module/xep/0166_jingle/jingle_flag.vala @@ -24,7 +24,12 @@ public class Xmpp.Xep.Jingle.Flag : XmppStreamFlag { public async Session? get_session(string sid) { if (promises.has_key(sid)) { - return yield promises[sid].future.wait_async(); + try { + return yield promises[sid].future.wait_async(); + } catch (FutureError e) { + warning("Failed waiting for session: %s", e.message); + return null; + } } return sessions[sid]; } diff --git a/xmpp-vala/src/module/xep/0166_jingle/session.vala b/xmpp-vala/src/module/xep/0166_jingle/session.vala index 22e8e978..aa8d6656 100644 --- a/xmpp-vala/src/module/xep/0166_jingle/session.vala +++ b/xmpp-vala/src/module/xep/0166_jingle/session.vala @@ -222,7 +222,12 @@ public class Xmpp.Xep.Jingle.Session : Object { .put_node(content.transport_params.to_transport_stanza_node("content-add"))); Iq.Stanza iq = new Iq.Stanza.set(content_add_node) { to=peer_full_jid }; - yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + try { + yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + } catch (IOError e) { + warning("Error adding content: %s", e.message); + // FIXME: Probably need to clean up some state + } } private void handle_content_accept(ContentNode content_node) throws IqError { diff --git a/xmpp-vala/src/module/xep/0176_jingle_ice_udp/transport_parameters.vala b/xmpp-vala/src/module/xep/0176_jingle_ice_udp/transport_parameters.vala index 490cc125..53057d9e 100644 --- a/xmpp-vala/src/module/xep/0176_jingle_ice_udp/transport_parameters.vala +++ b/xmpp-vala/src/module/xep/0176_jingle_ice_udp/transport_parameters.vala @@ -39,7 +39,11 @@ public abstract class Xmpp.Xep.JingleIceUdp.IceUdpTransportParameters : Jingle.T remote_pwd = node.get_attribute("pwd"); remote_ufrag = node.get_attribute("ufrag"); foreach (StanzaNode candidateNode in node.get_subnodes("candidate")) { - remote_candidates.add(Candidate.parse(candidateNode)); + try { + remote_candidates.add(Candidate.parse(candidateNode)); + } catch (Jingle.IqError e) { + warning("Ignoring invalid candidate %s: %s", candidateNode.to_string(), e.message); + } } StanzaNode? fingerprint_node = node.get_subnode("fingerprint", DTLS_NS_URI); diff --git a/xmpp-vala/src/module/xep/0191_blocking_command.vala b/xmpp-vala/src/module/xep/0191_blocking_command.vala index 9e5ede78..c037c480 100644 --- a/xmpp-vala/src/module/xep/0191_blocking_command.vala +++ b/xmpp-vala/src/module/xep/0191_blocking_command.vala @@ -88,11 +88,15 @@ public class Module : XmppStreamModule, Iq.Handler { bool has_feature = yield stream.get_module(ServiceDiscovery.Module.IDENTITY).has_entity_feature(stream, stream.remote_name, NS_URI); if (has_feature) { stream.add_flag(new Flag()); - stream.get_flag(Flag.IDENTITY).blocklist = yield get_blocklist(stream); + try { + stream.get_flag(Flag.IDENTITY).blocklist = yield get_blocklist(stream); + } catch (IOError e) { + warning("Failed to retrieve blocklist: %s", e.message); + } } } - private async Gee.List get_blocklist(XmppStream stream) { + private async Gee.List get_blocklist(XmppStream stream) throws IOError { StanzaNode blocklist_node = new StanzaNode.build("blocklist", NS_URI).add_self_xmlns(); Iq.Stanza iq = new Iq.Stanza.get(blocklist_node); diff --git a/xmpp-vala/src/module/xep/0199_ping.vala b/xmpp-vala/src/module/xep/0199_ping.vala index 18fa538c..7bc234bc 100644 --- a/xmpp-vala/src/module/xep/0199_ping.vala +++ b/xmpp-vala/src/module/xep/0199_ping.vala @@ -6,7 +6,7 @@ namespace Xmpp.Xep.Ping { public class Module : XmppStreamModule, Iq.Handler { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0199_ping"); - public async Iq.Stanza send_ping(XmppStream stream, Jid jid) { + public async Iq.Stanza send_ping(XmppStream stream, Jid jid) throws IOError { StanzaNode ping_node = new StanzaNode.build("ping", NS_URI).add_self_xmlns(); Iq.Stanza iq = new Iq.Stanza.get(ping_node) { to=jid }; return yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq, Priority.HIGH); diff --git a/xmpp-vala/src/module/xep/0215_external_service_discovery.vala b/xmpp-vala/src/module/xep/0215_external_service_discovery.vala index 5bad71cd..67f67c05 100644 --- a/xmpp-vala/src/module/xep/0215_external_service_discovery.vala +++ b/xmpp-vala/src/module/xep/0215_external_service_discovery.vala @@ -4,7 +4,7 @@ namespace Xmpp.Xep.ExternalServiceDiscovery { private const string NS_URI = "urn:xmpp:extdisco:2"; - public static async Gee.List request_services(XmppStream stream) { + public static async Gee.List request_services(XmppStream stream) throws IOError { Iq.Stanza request_iq = new Iq.Stanza.get((new StanzaNode.build("services", NS_URI)).add_self_xmlns()) { to=stream.remote_name }; Iq.Stanza response_iq = yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, request_iq); diff --git a/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala b/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala index f85049ac..43edefad 100644 --- a/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala +++ b/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala @@ -42,7 +42,7 @@ public class Module : Jingle.ContentType, XmppStreamModule { return yield stream.get_module(Jingle.Module.IDENTITY).is_available(stream, required_transport_type, required_components, full_jid); } - public async void offer_file_stream(XmppStream stream, Jid receiver_full_jid, InputStream input_stream, string basename, int64 size, string? precondition_name = null, Object? precondition_options = null) throws Jingle.Error { + public async void offer_file_stream(XmppStream stream, Jid receiver_full_jid, InputStream input_stream, string basename, int64 size, string? precondition_name = null, Object? precondition_options = null) throws Jingle.Error, Jingle.IqError { StanzaNode file_node; StanzaNode description = new StanzaNode.build("description", NS_URI) .add_self_xmlns() diff --git a/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala b/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala index 852cc7eb..7f44bda2 100644 --- a/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala +++ b/xmpp-vala/src/module/xep/0260_jingle_socks5_bytestreams.vala @@ -328,9 +328,13 @@ class LocalListener { } } catch (Error e) { warning("Jingle SOCKS5 bytestream establish error cid %s: %s", cid, e.message); - // Send a "general SOCKS server failure" (0x01) - yield conn.output_stream.write_all_async({0x05, 0x01}, GLib.Priority.DEFAULT, null, out written); - yield conn.output_stream.close_async(); + try { + // Send a "general SOCKS server failure" (0x01) + yield conn.output_stream.write_all_async({0x05, 0x01}, GLib.Priority.DEFAULT, null, out written); + yield conn.output_stream.close_async(); + } catch (Error sub) { + // Ignoring + } } } diff --git a/xmpp-vala/src/module/xep/0272_muji.vala b/xmpp-vala/src/module/xep/0272_muji.vala index 8226da10..7fd0da19 100644 --- a/xmpp-vala/src/module/xep/0272_muji.vala +++ b/xmpp-vala/src/module/xep/0272_muji.vala @@ -86,7 +86,12 @@ namespace Xmpp.Xep.Muji { GroupCall group_call = stream.get_flag(Flag.IDENTITY).calls[muc_jid]; group_call.waiting_for_finish_prepares[promise] = preparing_peers; - return yield promise.future.wait_async(); + try { + return yield promise.future.wait_async(); + } catch (FutureError e) { + warning("Failed waiting for preparing peers: %s", e.message); + return new ArrayList(); + } } private async void compute_payload_intersection(XmppStream stream, GroupCall group_call, string media) { diff --git a/xmpp-vala/src/module/xep/0280_message_carbons.vala b/xmpp-vala/src/module/xep/0280_message_carbons.vala index b396ee54..f8008bfe 100644 --- a/xmpp-vala/src/module/xep/0280_message_carbons.vala +++ b/xmpp-vala/src/module/xep/0280_message_carbons.vala @@ -10,13 +10,21 @@ public class Module : XmppStreamModule { public async void enable(XmppStream stream) { if (stream.get_flag(Flag.IDENTITY) == null) { Iq.Stanza iq = new Iq.Stanza.set(new StanzaNode.build("enable", NS_URI).add_self_xmlns()); - yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + try { + yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + } catch (IOError e) { + warning("Failed enabling carbons: %s", e.message); + } } } public async void disable(XmppStream stream) { Iq.Stanza iq = new Iq.Stanza.set(new StanzaNode.build("disable", NS_URI).add_self_xmlns()); - yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + try { + yield stream.get_module(Iq.Module.IDENTITY).send_iq_async(stream, iq); + } catch (IOError e) { + warning("Failed enabling carbons: %s", e.message); + } } public override void attach(XmppStream stream) { diff --git a/xmpp-vala/src/module/xep/0313_2_message_archive_management.vala b/xmpp-vala/src/module/xep/0313_2_message_archive_management.vala index 298a1c61..17b93d55 100644 --- a/xmpp-vala/src/module/xep/0313_2_message_archive_management.vala +++ b/xmpp-vala/src/module/xep/0313_2_message_archive_management.vala @@ -61,7 +61,7 @@ namespace Xmpp.MessageArchiveManagement.V2 { return MessageArchiveManagement.create_base_query(stream, mam_params.query_id, fields); } - public async QueryResult query_archive(XmppStream stream, MamQueryParams mam_params, Cancellable? cancellable = null) { + public async QueryResult query_archive(XmppStream stream, MamQueryParams mam_params, Cancellable? cancellable = null) throws IOError { var query_node = create_base_query(stream, mam_params); if (!mam_params.use_ns2_extended) { query_node.put_node(ResultSetManagement.create_set_rsm_node_before(mam_params.end_id)); @@ -70,7 +70,7 @@ namespace Xmpp.MessageArchiveManagement.V2 { return yield MessageArchiveManagement.query_archive(stream, mam_params.mam_server, query_node, cancellable); } - public async QueryResult page_through_results(XmppStream stream, MamQueryParams mam_params, QueryResult prev_result, Cancellable? cancellable = null) { + public async QueryResult page_through_results(XmppStream stream, MamQueryParams mam_params, QueryResult prev_result, Cancellable? cancellable = null) throws IOError { var query_node = create_base_query(stream, mam_params); query_node.put_node(ResultSetManagement.create_set_rsm_node_before(prev_result.first)); diff --git a/xmpp-vala/src/module/xep/0313_message_archive_management.vala b/xmpp-vala/src/module/xep/0313_message_archive_management.vala index a9149d4e..f054a047 100644 --- a/xmpp-vala/src/module/xep/0313_message_archive_management.vala +++ b/xmpp-vala/src/module/xep/0313_message_archive_management.vala @@ -57,7 +57,7 @@ public class Module : XmppStreamModule { return query_node; } - internal async QueryResult query_archive(XmppStream stream, Jid? mam_server, StanzaNode query_node, Cancellable? cancellable = null) { + internal async QueryResult query_archive(XmppStream stream, Jid? mam_server, StanzaNode query_node, Cancellable? cancellable = null) throws IOError { var res = new QueryResult(); Flag flag = Flag.get_flag(stream); diff --git a/xmpp-vala/src/module/xep/0392_consistent_color/hsluv.vala b/xmpp-vala/src/module/xep/0392_consistent_color/hsluv.vala index b45d84de..10aa5d9f 100644 --- a/xmpp-vala/src/module/xep/0392_consistent_color/hsluv.vala +++ b/xmpp-vala/src/module/xep/0392_consistent_color/hsluv.vala @@ -340,9 +340,9 @@ internal string rgb_to_hex(double[] tuple) { internal double[] hex_to_tgb(string hex) { return new double[] { - hex.substring(1, 2).to_long(null, 16) / 255.0, - hex.substring(3, 2).to_long(null, 16) / 255.0, - hex.substring(5, 2).to_long(null, 16) / 255.0 + long.parse(hex.substring(1, 2), 16) / 255.0, + long.parse(hex.substring(3, 2), 16) / 255.0, + long.parse(hex.substring(5, 2), 16) / 255.0 }; } diff --git a/xmpp-vala/src/module/xep/0402_bookmarks2.vala b/xmpp-vala/src/module/xep/0402_bookmarks2.vala index 938af0e9..3a7e5211 100644 --- a/xmpp-vala/src/module/xep/0402_bookmarks2.vala +++ b/xmpp-vala/src/module/xep/0402_bookmarks2.vala @@ -8,7 +8,7 @@ public const string NS_URI_COMPAT = NS_URI + "#compat"; public class Module : BookmarksProvider, XmppStreamModule { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0402_bookmarks2"); - public async Set? get_conferences(XmppStream stream) { + public async Set? get_conferences(XmppStream stream) throws IOError { HashMap? hm = null; Flag? flag = stream.get_flag(Flag.IDENTITY); @@ -35,7 +35,7 @@ public class Module : BookmarksProvider, XmppStreamModule { return ret; } - public async void add_conference(XmppStream stream, Conference conference) { + public async void add_conference(XmppStream stream, Conference conference) throws IOError { StanzaNode conference_node = new StanzaNode.build("conference", NS_URI).add_self_xmlns() .put_attribute("autojoin", conference.autojoin.to_string()); if (conference.name != null) { @@ -56,7 +56,7 @@ public class Module : BookmarksProvider, XmppStreamModule { yield stream.get_module(Pubsub.Module.IDENTITY).publish(stream, stream.get_flag(Bind.Flag.IDENTITY).my_jid.bare_jid, NS_URI, conference.jid.to_string(), conference_node, publish_options); } - public async void replace_conference(XmppStream stream, Jid muc_jid, Conference modified_conference) { + public async void replace_conference(XmppStream stream, Jid muc_jid, Conference modified_conference) throws IOError { yield add_conference(stream, modified_conference); } diff --git a/xmpp-vala/src/module/xep/0461_replies.vala b/xmpp-vala/src/module/xep/0461_replies.vala index af84aa3d..23849d69 100644 --- a/xmpp-vala/src/module/xep/0461_replies.vala +++ b/xmpp-vala/src/module/xep/0461_replies.vala @@ -36,6 +36,5 @@ namespace Xmpp.Xep.Replies { } catch (InvalidJidError e) { return null; } - return null; } } \ No newline at end of file diff --git a/xmpp-vala/tests/color.vala b/xmpp-vala/tests/color.vala index ded67d53..a00710c5 100644 --- a/xmpp-vala/tests/color.vala +++ b/xmpp-vala/tests/color.vala @@ -39,9 +39,9 @@ class ColorTest : Gee.TestCase { public void test_rgb_to_angle() { string[] colors = {"e57373", "f06292", "ba68c8", "9575cd", "7986cb", "64b5f6", "4fc3f7", "4dd0e1", "4db6ac", "81c784", "aed581", "dce775", "fff176", "ffd54f", "ffb74d", "ff8a65"}; foreach(string hex_color in colors) { - uint8 r = (uint8) ((double) hex_color.substring(0, 2).to_long(null, 16)); - uint8 g = (uint8) ((double) hex_color.substring(2, 2).to_long(null, 16)); - uint8 b = (uint8) ((double) hex_color.substring(4, 2).to_long(null, 16)); + uint8 r = (uint8) ((double) long.parse(hex_color.substring(0, 2), 16)); + uint8 g = (uint8) ((double) long.parse(hex_color.substring(2, 2), 16)); + uint8 b = (uint8) ((double) long.parse(hex_color.substring(4, 2), 16)); //print(@"$hex_color, $r, $g, $b, $(ConsistentColor.rgb_to_angle(r, g, b))\n"); } } diff --git a/xmpp-vala/tests/stanza.vala b/xmpp-vala/tests/stanza.vala index 42e19f9a..b573995f 100644 --- a/xmpp-vala/tests/stanza.vala +++ b/xmpp-vala/tests/stanza.vala @@ -21,11 +21,15 @@ class StanzaTest : Gee.TestCase { .put_node(new StanzaNode.build("testbb", "ns3_uri") .add_self_xmlns()); - var xml1 = node1.to_xml(); - var node2 = yield new StanzaReader.for_string(xml1).read_node(); - fail_if_not(node1.equals(node2)); - fail_if_not_eq_str(node1.to_string(), node2.to_string()); - cb(); + try { + var xml1 = node1.to_xml(); + var node2 = yield new StanzaReader.for_string(xml1).read_node(); + fail_if_not(node1.equals(node2)); + fail_if_not_eq_str(node1.to_string(), node2.to_string()); + cb(); + } catch (GLib.Error e) { + cb(e); + } } private async void test_typical_stream(Gee.TestFinishedCallback cb) { @@ -55,12 +59,16 @@ class StanzaTest : Gee.TestCase { .put_node(new StanzaNode.build("body") .put_node(new StanzaNode.text(" I'll send a friar with speed, to Mantua, with my letters to thy lord."))); - var reader = new StanzaReader.for_string(stream); - fail_if_not_eq_node(root_node_cmp, yield reader.read_root_node()); - fail_if_not_eq_node(node_cmp, yield reader.read_node()); - yield reader.read_node(); - yield fail_if_not_end_of_stream(reader); - cb(); + try { + var reader = new StanzaReader.for_string(stream); + fail_if_not_eq_node(root_node_cmp, yield reader.read_root_node()); + fail_if_not_eq_node(node_cmp, yield reader.read_node()); + yield reader.read_node(); + yield fail_if_not_end_of_stream(reader); + cb(); + } catch (GLib.Error e) { + cb(e); + } } private async void fail_if_not_end_of_stream(StanzaReader reader) { @@ -105,13 +113,17 @@ class StanzaTest : Gee.TestCase { .put_node(new StanzaNode.build("required", "urn:ietf:params:xml:ns:xmpp-bind"))); var node2_cmp = new StanzaNode.build("r", "http://jabber.org/protocol/ack"); - var reader = new StanzaReader.for_string(stream); - fail_if_not_eq_node(root_node_cmp, yield reader.read_root_node()); - fail_if_not_eq_node(node_cmp, yield reader.read_node()); - fail_if_not_eq_node(node2_cmp, yield reader.read_node()); - yield reader.read_node(); - yield fail_if_not_end_of_stream(reader); - cb(); + try { + var reader = new StanzaReader.for_string(stream); + fail_if_not_eq_node(root_node_cmp, yield reader.read_root_node()); + fail_if_not_eq_node(node_cmp, yield reader.read_node()); + fail_if_not_eq_node(node2_cmp, yield reader.read_node()); + yield reader.read_node(); + yield fail_if_not_end_of_stream(reader); + cb(); + } catch (GLib.Error e) { + cb(e); + } } private void test_encoded_val() { diff --git a/xmpp-vala/tests/testcase.vala b/xmpp-vala/tests/testcase.vala index 178b6353..10da78f6 100644 --- a/xmpp-vala/tests/testcase.vala +++ b/xmpp-vala/tests/testcase.vala @@ -62,7 +62,7 @@ public abstract class Gee.TestCase : Object { namespace Gee { public delegate void TestMethod (); - public delegate void TestFinishedCallback (); + public delegate void TestFinishedCallback (GLib.Error? error = null); public delegate void AsyncTestMethod (TestFinishedCallback cb); } @@ -128,8 +128,15 @@ private class Gee.TestAsyncAdaptor : Object, TestAdaptor { main_loop.run (); } - public void finish () { - Idle.add (() => { main_loop.quit (); return false; }); + public void finish (GLib.Error? error = null) { + Idle.add(() => { + main_loop.quit(); + if (error != null) { + Test.fail(); + Test.message("Error: %s", error.message); + } + return false; + }); } public bool finish_timeout () { -- cgit v1.3 From 3e136fc57a2e509e5a4dd265a798b196205b0a80 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sun, 4 Oct 2026 22:02:19 +0200 Subject: Fix more warnings --- libdino/src/service/avatar_manager.vala | 2 +- main/meson.build | 2 +- plugins/omemo/meson.build | 51 --------------------- xmpp-vala/src/core/stanza_node.vala | 2 +- xmpp-vala/src/core/stanza_reader.vala | 11 ++++- xmpp-vala/src/file_content_type.vala | 8 +++- xmpp-vala/src/module/xep/0004_data_forms.vala | 5 -- .../module/xep/0030_service_discovery/module.vala | 17 +++++-- xmpp-vala/src/module/xep/0084_user_avatars.vala | 9 ++-- .../xep/0261_jingle_in_band_bytestreams.vala | 4 -- xmpp-vala/src/module/xep/0272_muji.vala | 10 ++-- .../src/module/xep/0363_http_file_upload.vala | 36 ++++++++------- .../module/xep/0388_extensible_sasl_profile.vala | 24 ++++++---- .../module/xep/0392_consistent_color/hsluv.vala | 53 ++++++++++------------ xmpp-vala/src/module/xep/0410_muc_self_ping.vala | 18 +++++--- .../src/module/xep/0425_message_moderation.vala | 18 +++++--- .../module/xep/0447_stateless_file_sharing.vala | 2 +- .../0490_message_displayed_synchronization.vala | 37 ++++++++++----- xmpp-vala/tests/color.vala | 20 ++++---- xmpp-vala/tests/common.vala | 12 ++--- xmpp-vala/tests/weak_map.vala | 8 ++-- 21 files changed, 171 insertions(+), 178 deletions(-) delete mode 100644 plugins/omemo/meson.build (limited to 'xmpp-vala/src/module') diff --git a/libdino/src/service/avatar_manager.vala b/libdino/src/service/avatar_manager.vala index ac4971ef..7f69f508 100644 --- a/libdino/src/service/avatar_manager.vala +++ b/libdino/src/service/avatar_manager.vala @@ -142,7 +142,7 @@ public class AvatarManager : StreamInteractionModule, Object { public void unset_avatar(Account account) { XmppStream stream = stream_interactor.get_stream(account); if (stream == null) return; - Xmpp.Xep.UserAvatars.unset_avatar(stream); + Xmpp.Xep.UserAvatars.unset_avatar(stream, get_avatar_hash(account, account.bare_jid)); } private void on_account_added(Account account) { diff --git a/main/meson.build b/main/meson.build index cdefcbf7..d9f56e81 100644 --- a/main/meson.build +++ b/main/meson.build @@ -142,7 +142,7 @@ if get_option('rtp').allowed() and dep_gstreamer.found() and dep_gstreamer_app.f voice_sources = files( 'src/plugins/rtp/voice_processor_native.cpp', ) - voice_c_args = c_args + voice_c_args = ['-DG_LOG_DOMAIN="dino"'] if dep_webrtc_audio_processing.version().version_compare('>=2.0') voice_c_args += ['-DWEBRTC2'] elif dep_webrtc_audio_processing.version().version_compare('>=1.0') diff --git a/plugins/omemo/meson.build b/plugins/omemo/meson.build deleted file mode 100644 index 70279946..00000000 --- a/plugins/omemo/meson.build +++ /dev/null @@ -1,51 +0,0 @@ -subdir('po') -dependencies = [ - dep_libadwaita, - dep_dino, - dep_gee, - dep_glib, - dep_gmodule, - dep_gtk4, - dep_libomemo_c, - dep_m, - dep_xmpp_vala, -] -sources = files( -) -sources += gnome.compile_resources( - 'resources', - 'data/gresource.xml', - source_dir: 'data', -) -c_args = vala_c_args + [ - '-DG_LOG_DOMAIN="OMEMO"', - '-DGETTEXT_PACKAGE="dino-omemo"', - '-DLOCALE_INSTALL_DIR="@0@"'.format(get_option('prefix') / get_option('localedir')), -] -vala_args = [ - '--vapidir', meson.current_source_dir() / 'vapi', - # This is to build internal vapi for tests - '--header', meson.current_build_dir() / 'omemo.h', - '--internal-vapi', meson.current_build_dir() / 'omemo-internal.vapi', - '--internal-header', meson.current_build_dir() / 'omemo-internal.h', -] -lib_omemo = shared_library('omemo', sources, name_prefix: '', c_args: c_args, vala_args: vala_args, include_directories: include_directories('src'), dependencies: dependencies, install: true, install_dir: get_option('libdir') / get_option('plugindir'), install_rpath: default_install_rpath) -dep_omemo = declare_dependency(link_with: lib_omemo, include_directories: include_directories('.')) -# This is to use the internal vapi instead of the regular -vapi_omemo_internal = custom_target('omemo-internal-vapi', command: [find_program('touch'), meson.current_build_dir() / 'omemo-internal.vapi'], output: ['omemo-internal.vapi'], depends: lib_omemo) -dep_omemo_internal = declare_dependency(link_args: [lib_omemo.full_path()], include_directories: include_directories('.', 'src'), sources: [vapi_omemo_internal]) - -test_sources = [ - 'tests/native/common.vala', - 'tests/native/testcase.vala', - - 'tests/native/curve25519.vala', - 'tests/native/hkdf.vala', - 'tests/native/session_builder.vala', -] -test_vala_args = [ - '--vapidir', meson.current_source_dir() / 'vapi', -] - -exe_omemo_test = executable('omemo-test', test_sources, c_args: c_args, vala_args: test_vala_args, dependencies: dependencies + dep_omemo_internal, build_rpath: '$ORIGIN', install: false) -test('Tests for omemo', exe_omemo_test) diff --git a/xmpp-vala/src/core/stanza_node.vala b/xmpp-vala/src/core/stanza_node.vala index 7a68da62..56f857d4 100644 --- a/xmpp-vala/src/core/stanza_node.vala +++ b/xmpp-vala/src/core/stanza_node.vala @@ -29,7 +29,7 @@ public abstract class StanzaEntry { case '\'': result_builder.append("'"); break; case '<': result_builder.append("<"); break; case '>': result_builder.append(">"); break; - default: error("Unreachable"); break; + default: error("Unreachable"); } return false; }); diff --git a/xmpp-vala/src/core/stanza_reader.vala b/xmpp-vala/src/core/stanza_reader.vala index ff512497..4828600d 100644 --- a/xmpp-vala/src/core/stanza_reader.vala +++ b/xmpp-vala/src/core/stanza_reader.vala @@ -38,8 +38,15 @@ public class StanzaReader { if (cancellable != null && cancellable.is_cancelled()) throw new IOError.CANCELLED("Input stream is canceled."); try { buffer_fill = (int) yield ((!)input).read_async(buffer, GLib.Priority.DEFAULT, cancellable); - } catch (TlsError.EOF e) { - throw new IOError.CLOSED("End of TLS stream reached"); + } catch (Error e) { + if (e is IOError) { + throw (IOError) e; + } else if (e is TlsError.EOF) { + // The error can be TlsError.EOF instead of IOError.CLOSED, fixing that + throw new IOError.CLOSED("End of TLS stream reached"); + } else { + throw new IOError.FAILED("Unknown error: %s", e.message); + } } if (buffer_fill == 0) throw new IOError.CLOSED("End of input stream reached."); buffer_pos = 0; diff --git a/xmpp-vala/src/file_content_type.vala b/xmpp-vala/src/file_content_type.vala index 3656435e..bae493f6 100644 --- a/xmpp-vala/src/file_content_type.vala +++ b/xmpp-vala/src/file_content_type.vala @@ -14,8 +14,12 @@ namespace Xmpp { } public FileContentType.from_file(File file) { - FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE); - this.from_file_info(file_info); + try { + FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE); + this.from_file_info(file_info); + } catch (Error e) { + warning("Failed reading file content type: %s", e.message); + } } public string? get_mime_type() { diff --git a/xmpp-vala/src/module/xep/0004_data_forms.vala b/xmpp-vala/src/module/xep/0004_data_forms.vala index f481e174..6c16a53d 100644 --- a/xmpp-vala/src/module/xep/0004_data_forms.vala +++ b/xmpp-vala/src/module/xep/0004_data_forms.vala @@ -83,11 +83,6 @@ public class DataForm { value_node.put_node(new StanzaNode.text(val)); } - internal void add_value_string(string val) { - StanzaNode node = new StanzaNode.build("value"); - node.put_node(new StanzaNode.text(val)); - } - internal Gee.List