From 349750105a49132628bb2ff9ba3b29040459f981 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sat, 21 Oct 2017 22:48:50 +0200 Subject: [PATCH 01/10] global: applied uncrustify --- src/crypt/certificate.vala | 325 ++-- src/mconnect/application.vala | 140 +- src/mconnect/battery-proxy.vala | 134 +- src/mconnect/battery.vala | 59 +- src/mconnect/config.vala | 189 +- src/mconnect/core.vala | 205 +- src/mconnect/device-proxy.vala | 489 ++--- src/mconnect/device.vala | 1165 ++++++------ src/mconnect/devicechannel.vala | 545 +++--- src/mconnect/devicemanager-proxy.vala | 308 +-- src/mconnect/devicemanager.vala | 489 +++-- src/mconnect/discovereddevice.vala | 111 +- src/mconnect/discovery.vala | 130 +- src/mconnect/io-job.vala | 92 +- src/mconnect/logging.vala | 24 +- src/mconnect/main.vala | 15 +- src/mconnect/mousepad.vala | 266 ++- src/mconnect/notification.vala | 239 ++- src/mconnect/packet.vala | 302 +-- .../packethandlerinterface-proxy.vala | 4 +- src/mconnect/packethandlerinterface.vala | 7 +- src/mconnect/packethandlers-proxy.vala | 48 +- src/mconnect/packethandlers.vala | 93 +- src/mconnect/ping-proxy.vala | 56 +- src/mconnect/ping.vala | 51 +- src/mconnect/property-proxy.vala | 118 +- src/mconnect/share-proxy.vala | 62 +- src/mconnect/share.vala | 376 ++-- src/mconnect/telephony-proxy.vala | 36 +- src/mconnect/telephony.vala | 210 ++- src/mconnect/transfer-download.vala | 332 ++-- src/mconnect/transfer-interface.vala | 13 +- src/mconnect/transfer-manager-proxy.vala | 177 +- src/mconnect/transfer-manager.vala | 61 +- src/mconnect/transfer-proxy.vala | 56 +- src/mconnect/transfer-upload.vala | 330 ++-- src/mconnect/utils.vala | 346 ++-- src/mconnectctl/device-iface.vala | 55 +- src/mconnectctl/device-manager-iface.vala | 12 +- src/mconnectctl/main.vala | 703 ++++--- src/mconnectctl/share-iface.vala | 13 +- src/mconnectctl/telephony-iface.vala | 11 +- test/mconn-crypt-vala-test.vala | 198 +- test/mconn-utils-test.vala | 70 +- uncrustify.cfg | 1645 +++++++++++++++++ 45 files changed, 6029 insertions(+), 4281 deletions(-) create mode 100644 uncrustify.cfg diff --git a/src/crypt/certificate.vala b/src/crypt/certificate.vala index d8f207b..6521bc7 100644 --- a/src/crypt/certificate.vala +++ b/src/crypt/certificate.vala @@ -20,162 +20,171 @@ namespace Mconn { - namespace Crypt { - - private GnuTLS.X509.PrivateKey generate_private_key() { - var key = GnuTLS.X509.PrivateKey.create(); - - key.generate(GnuTLS.PKAlgorithm.RSA, 2048); - // size_t sz = 4096; - // var buf = GnuTLS.malloc(sz); - // key.export_pkcs8(GnuTLS.X509.CertificateFormat.PEM, "", - // GnuTLS.X509.PKCSEncryptFlags.PLAIN, - // buf, ref sz); - - // stdout.printf("private key:\n"); - // stdout.printf("%s", (string)buf); - - // GnuTLS.free(buf); - - return key; - } - - private struct dn_setting { - string oid; - string name; - } - - GnuTLS.X509.Certificate generate_self_signed_cert(GnuTLS.X509.PrivateKey key, string common_name) { - - var cert = GnuTLS.X509.Certificate.create(); - var start_time = new DateTime.now_local(); - var end_time = start_time.add_years(10); - - cert.set_key(key); - cert.set_version(1); - cert.set_activation_time((time_t)start_time.to_unix()); - cert.set_expiration_time((time_t)end_time.to_unix()); - uint32 serial = Posix.htonl(10); - cert.set_serial(&serial, sizeof(uint32)); - - dn_setting[] dn = { - dn_setting() { oid=GnuTLS.OID.X520_ORGANIZATION_NAME, - name="mconnect"}, - dn_setting() { oid=GnuTLS.OID.X520_ORGANIZATIONAL_UNIT_NAME, - name="mconnect"}, - dn_setting() { oid=GnuTLS.OID.X520_COMMON_NAME, - name=common_name}, - }; - foreach (var dn_val in dn) { - var err = cert.set_dn_by_oid(dn_val.oid, 0, - dn_val.name.data, dn_val.name.length); - if (err != GnuTLS.ErrorCode.SUCCESS ) { - warning("set dn failed for OID %s - %s, err: %d\n", - dn_val.oid, dn_val.name, err); - } - } - - - var err = cert.sign(cert, key); - GLib.assert(err == GnuTLS.ErrorCode.SUCCESS); - - // size_t sz = 8192; - // var buf = GnuTLS.malloc(sz); - // err = cert.export(GnuTLS.X509.CertificateFormat.PEM, buf, ref sz); - // if (err != GnuTLS.ErrorCode.SUCCESS) { - // if (err == GnuTLS.ErrorCode.SHORT_MEMORY_BUFFER) { - // stdout.printf("too short\n"); - // } else { - // stdout.printf("other error: %d\n", err); - // } - // } else { - // stdout.printf("certificate:\n"); - // stdout.printf("size: %zu\n", sz); - // stdout.printf("%s", (string)buf); - // } - // GnuTLS.free(buf); - - return cert; - } - - private uint8[] export_certificate(GnuTLS.X509.Certificate cert) { - var buf = new uint8[8192]; - size_t sz = buf.length; - - - var err = cert.export(GnuTLS.X509.CertificateFormat.PEM, buf, ref sz); - assert(err == GnuTLS.ErrorCode.SUCCESS); - - debug("actual certificate PEM size: %zu", sz); - debug("certificate PEM:\n%s", (string)buf); - - // TODO: figure out if this is valid at all - buf.length = (int) sz; - - return buf; - } - - private uint8[] export_private_key(GnuTLS.X509.PrivateKey key) { - var buf = new uint8[8192]; - size_t sz = buf.length; - - var err = key.export_pkcs8(GnuTLS.X509.CertificateFormat.PEM, "", - GnuTLS.X509.PKCSEncryptFlags.PLAIN, - buf, ref sz); - assert(err == GnuTLS.ErrorCode.SUCCESS); - debug("actual private key PEM size: %zu", sz); - debug("private key PEM:\n%s", (string)buf); - - // TODO: figure out if this is valid at all - buf.length = (int) sz; - return buf; - } - - private void export_to_file(string path, uint8[] data) throws Error { - var f = File.new_for_path(path); - - f.replace_contents(data, "", false, - FileCreateFlags.PRIVATE | FileCreateFlags.REPLACE_DESTINATION, - null); - } - - public void generate_key_cert(string key_path, string cert_path, string name) throws Error { - var key = generate_private_key(); - var cert = generate_self_signed_cert(key, name); - - export_to_file(cert_path, export_certificate(cert)); - export_to_file(key_path, export_private_key(key)); - } - - private GnuTLS.X509.Certificate cert_from_pem(string certificate_pem) { - var datum = GnuTLS.Datum() { data=certificate_pem.data, - size=certificate_pem.data.length }; - - var cert = GnuTLS.X509.Certificate.create(); - var res = cert.import(ref datum, GnuTLS.X509.CertificateFormat.PEM); - assert(res == GnuTLS.ErrorCode.SUCCESS); - return cert; - } - - /** - * fingerprint_certificate: - * Produce a SHA1 fingerprint of the certificate - * - * @param certificate_pem PEM encoded certificate - * @return SHA1 fingerprint as bytes - */ - public uint8[] fingerprint_certificate(string certificate_pem) { - var cert = cert_from_pem(certificate_pem); - - // TOOD: make digest configurable, for now assume it's SHA1 - var data = new uint8[20]; - size_t sz = data.length; - var res = cert.get_fingerprint(GnuTLS.DigestAlgorithm.SHA1, - data, ref sz); - assert(res == GnuTLS.ErrorCode.SUCCESS); - assert(sz == data.length); - - return data; - } - } + namespace Crypt { + + private GnuTLS.X509.PrivateKey generate_private_key () { + var key = GnuTLS.X509.PrivateKey.create (); + + key.generate (GnuTLS.PKAlgorithm.RSA, 2048); + // size_t sz = 4096; + // var buf = GnuTLS.malloc(sz); + // key.export_pkcs8(GnuTLS.X509.CertificateFormat.PEM, "", + // GnuTLS.X509.PKCSEncryptFlags.PLAIN, + // buf, ref sz); + + // stdout.printf("private key:\n"); + // stdout.printf("%s", (string)buf); + + // GnuTLS.free(buf); + + return key; + } + + private struct dn_setting { + string oid; + string name; + } + + GnuTLS.X509.Certificate generate_self_signed_cert (GnuTLS.X509.PrivateKey key, + string common_name) { + + var cert = GnuTLS.X509.Certificate.create (); + var start_time = new DateTime.now_local (); + var end_time = start_time.add_years (10); + + cert.set_key (key); + cert.set_version (1); + cert.set_activation_time ((time_t) start_time.to_unix ()); + cert.set_expiration_time ((time_t) end_time.to_unix ()); + uint32 serial = Posix.htonl (10); + cert.set_serial (&serial, sizeof (uint32)); + + dn_setting[] dn = { + dn_setting () { + oid = GnuTLS.OID.X520_ORGANIZATION_NAME, + name = "mconnect" + }, + dn_setting () { + oid = GnuTLS.OID.X520_ORGANIZATIONAL_UNIT_NAME, + name = "mconnect" + }, + dn_setting () { + oid = GnuTLS.OID.X520_COMMON_NAME, + name = common_name + }, + }; + foreach (var dn_val in dn) { + var err = cert.set_dn_by_oid (dn_val.oid, 0, + dn_val.name.data, dn_val.name.length); + if (err != GnuTLS.ErrorCode.SUCCESS) { + warning ("set dn failed for OID %s - %s, err: %d\n", + dn_val.oid, dn_val.name, err); + } + } + + + var err = cert.sign (cert, key); + GLib.assert (err == GnuTLS.ErrorCode.SUCCESS); + + // size_t sz = 8192; + // var buf = GnuTLS.malloc(sz); + // err = cert.export(GnuTLS.X509.CertificateFormat.PEM, buf, ref sz); + // if (err != GnuTLS.ErrorCode.SUCCESS) { + // if (err == GnuTLS.ErrorCode.SHORT_MEMORY_BUFFER) { + // stdout.printf("too short\n"); + // } else { + // stdout.printf("other error: %d\n", err); + // } + // } else { + // stdout.printf("certificate:\n"); + // stdout.printf("size: %zu\n", sz); + // stdout.printf("%s", (string)buf); + // } + // GnuTLS.free(buf); + + return cert; + } + + private uint8[] export_certificate (GnuTLS.X509.Certificate cert) { + var buf = new uint8[8192]; + size_t sz = buf.length; + + + var err = cert.export (GnuTLS.X509.CertificateFormat.PEM, buf, ref sz); + assert (err == GnuTLS.ErrorCode.SUCCESS); + + debug ("actual certificate PEM size: %zu", sz); + debug ("certificate PEM:\n%s", (string) buf); + + // TODO: figure out if this is valid at all + buf.length = (int) sz; + + return buf; + } + + private uint8[] export_private_key (GnuTLS.X509.PrivateKey key) { + var buf = new uint8[8192]; + size_t sz = buf.length; + + var err = key.export_pkcs8 (GnuTLS.X509.CertificateFormat.PEM, "", + GnuTLS.X509.PKCSEncryptFlags.PLAIN, + buf, ref sz); + assert (err == GnuTLS.ErrorCode.SUCCESS); + debug ("actual private key PEM size: %zu", sz); + debug ("private key PEM:\n%s", (string) buf); + + // TODO: figure out if this is valid at all + buf.length = (int) sz; + return buf; + } + + private void export_to_file (string path, uint8[] data) throws Error { + var f = File.new_for_path (path); + + f.replace_contents (data, "", false, + FileCreateFlags.PRIVATE | FileCreateFlags.REPLACE_DESTINATION, + null); + } + + public void generate_key_cert (string key_path, string cert_path, string name) throws Error { + var key = generate_private_key (); + var cert = generate_self_signed_cert (key, name); + + export_to_file (cert_path, export_certificate (cert)); + export_to_file (key_path, export_private_key (key)); + } + + private GnuTLS.X509.Certificate cert_from_pem (string certificate_pem) { + var datum = GnuTLS.Datum () { + data = certificate_pem.data, + size = certificate_pem.data.length + }; + + var cert = GnuTLS.X509.Certificate.create (); + var res = cert.import (ref datum, GnuTLS.X509.CertificateFormat.PEM); + assert (res == GnuTLS.ErrorCode.SUCCESS); + return cert; + } + + /** + * fingerprint_certificate: + * Produce a SHA1 fingerprint of the certificate + * + * @param certificate_pem PEM encoded certificate + * @return SHA1 fingerprint as bytes + */ + public uint8[] fingerprint_certificate (string certificate_pem) { + var cert = cert_from_pem (certificate_pem); + + // TOOD: make digest configurable, for now assume it's SHA1 + var data = new uint8[20]; + size_t sz = data.length; + var res = cert.get_fingerprint (GnuTLS.DigestAlgorithm.SHA1, + data, ref sz); + assert (res == GnuTLS.ErrorCode.SUCCESS); + assert (sz == data.length); + + return data; + } + } } \ No newline at end of file diff --git a/src/mconnect/application.vala b/src/mconnect/application.vala index bf696ce..effdb51 100644 --- a/src/mconnect/application.vala +++ b/src/mconnect/application.vala @@ -20,98 +20,98 @@ namespace Mconn { - public class Application : GLib.Application { + public class Application : GLib.Application { - private Core core = null; + private Core core = null; - private static bool log_debug = false; - private static bool log_debug_verbose = false; + private static bool log_debug = false; + private static bool log_debug_verbose = false; - private const GLib.OptionEntry[] options = { - {"debug", 'd', 0, OptionArg.NONE, ref log_debug, - "Show debug output", null}, - {"verbose-debug", 0, 0, OptionArg.NONE, ref log_debug_verbose, - "Show verbose debug output", null}, - {null} - }; + private const GLib.OptionEntry[] options = { + { "debug", 'd', 0, OptionArg.NONE, ref log_debug, + "Show debug output", null }, + { "verbose-debug", 0, 0, OptionArg.NONE, ref log_debug_verbose, + "Show verbose debug output", null }, + { null } + }; - private Discovery discovery = null; - private DeviceManager manager = null; - private DeviceManagerDBusProxy bus_manager = null; - private TransferManager transfer = null; - private TransferManagerDBusProxy bus_transfer = null; + private Discovery discovery = null; + private DeviceManager manager = null; + private DeviceManagerDBusProxy bus_manager = null; + private TransferManager transfer = null; + private TransferManagerDBusProxy bus_transfer = null; - public Application() { - Object(application_id: "org.mconnect"); - add_main_option_entries(options); + public Application () { + Object (application_id: "org.mconnect"); + add_main_option_entries (options); - discovery = new Discovery(); - manager = new DeviceManager(); - transfer = new TransferManager(); - } + discovery = new Discovery (); + manager = new DeviceManager (); + transfer = new TransferManager (); + } - protected override void startup() { - debug("startup"); + protected override void startup () { + debug ("startup"); - base.startup(); + base.startup (); - if (log_debug == true) - Environment.set_variable("G_MESSAGES_DEBUG", "all", false); + if (log_debug == true) + Environment.set_variable ("G_MESSAGES_DEBUG", "all", false); - if (log_debug_verbose == true) - Logging.enable_vdebug(); + if (log_debug_verbose == true) + Logging.enable_vdebug (); - core = Core.instance(); - if (core == null) - error("cannot initialize core"); + core = Core.instance (); + if (core == null) + error ("cannot initialize core"); - core.transfer_manager = this.transfer; + core.transfer_manager = this.transfer; - if (core.config.is_debug_on() == true) - Environment.set_variable("G_MESSAGES_DEBUG", "all", false); + if (core.config.is_debug_on () == true) + Environment.set_variable ("G_MESSAGES_DEBUG", "all", false); - Notify.init("mconnect"); + Notify.init ("mconnect"); - discovery.device_found.connect((disc, discdev) => { - manager.handle_discovered_device(discdev); - }); + discovery.device_found.connect ((disc, discdev) => { + manager.handle_discovered_device (discdev); + }); - try { - discovery.listen(); - } catch (Error e) { - message("failed to setup device listener: %s", e.message); - } - } + try { + discovery.listen (); + } catch (Error e) { + message ("failed to setup device listener: %s", e.message); + } + } - protected override void activate() { - debug("activate"); - // reload devices from cache - manager.load_cache(); - hold(); - } + protected override void activate () { + debug ("activate"); + // reload devices from cache + manager.load_cache (); + hold (); + } - public override bool dbus_register(DBusConnection conn, - string object_path) throws Error { + public override bool dbus_register (DBusConnection conn, + string object_path) throws Error { - this.bus_manager = new DeviceManagerDBusProxy.with_manager(conn, - this.manager); - this.bus_manager.publish(); + this.bus_manager = new DeviceManagerDBusProxy.with_manager (conn, + this.manager); + this.bus_manager.publish (); - this.bus_transfer = new TransferManagerDBusProxy.with_manager(conn, - this.transfer); - this.bus_transfer.publish(); + this.bus_transfer = new TransferManagerDBusProxy.with_manager (conn, + this.transfer); + this.bus_transfer.publish (); - base.dbus_register(conn, object_path); - debug("dbus register, path %s", object_path); + base.dbus_register (conn, object_path); + debug ("dbus register, path %s", object_path); - return true; - } + return true; + } - public override void dbus_unregister(DBusConnection conn, - string object_path) { + public override void dbus_unregister (DBusConnection conn, + string object_path) { - base.dbus_unregister(conn, object_path); - debug("dbus unregister, path %s", object_path); - } - } + base.dbus_unregister (conn, object_path); + debug ("dbus unregister, path %s", object_path); + } + } } \ No newline at end of file diff --git a/src/mconnect/battery-proxy.vala b/src/mconnect/battery-proxy.vala index 18fbfda..bcf70e6 100644 --- a/src/mconnect/battery-proxy.vala +++ b/src/mconnect/battery-proxy.vala @@ -21,69 +21,73 @@ [DBus (name = "org.mconnect.Device.Battery")] class BatteryHandlerProxy : Object, PacketHandlerInterfaceProxy { - private Device device = null; - private BatteryHandler battery_handler = null; - private uint register_id = 0; - private ulong notify_id = 0; - private DBusPropertyNotifier prop_notifier = null; - - public uint level { get; private set; default = 0; } - public bool charging { get; private set; default = false; } - - public BatteryHandlerProxy.for_device_handler(Device dev, - PacketHandlerInterface iface) { - this.device = dev; - - this.battery_handler = (BatteryHandler) iface; - - this.battery_handler.battery.connect(this.battery_change); - } - - private void battery_change(Device dev, uint level, bool charging) { - if (this.device != dev) - return; - - this.level = level; - this.charging = charging; - } - - [DBus (visible = false)] - public void bus_register(DBusConnection conn, string path) throws IOError { - if (this.register_id == 0) - this.register_id = conn.register_object(path, this); - - this.prop_notifier = new DBusPropertyNotifier(conn, - "org.mconnect.Device.Battery", - path); - - this.notify.connect(this.send_property_change); - } - - [DBus (visible = false)] - public void bus_unregister(DBusConnection conn) throws IOError { - if (this.register_id != 0) - conn.unregister_object(this.register_id); - this.register_id = 0; - - this.notify.disconnect(this.send_property_change); - this.notify_id = 0; - } - - private void send_property_change(ParamSpec p) { - assert(this.prop_notifier != null); - - Variant v = null; - - if (p.name == "level") { - v = this.level; - } - if (p.name == "charging") { - v = this.charging; - } - - if (v == null) - return; - - this.prop_notifier.queue_property_change(p.name, v); - } + private Device device = null; + private BatteryHandler battery_handler = null; + private uint register_id = 0; + private ulong notify_id = 0; + private DBusPropertyNotifier prop_notifier = null; + + public uint level { + get; private set; default = 0; + } + public bool charging { + get; private set; default = false; + } + + public BatteryHandlerProxy.for_device_handler (Device dev, + PacketHandlerInterface iface) { + this.device = dev; + + this.battery_handler = (BatteryHandler) iface; + + this.battery_handler.battery.connect (this.battery_change); + } + + private void battery_change (Device dev, uint level, bool charging) { + if (this.device != dev) + return; + + this.level = level; + this.charging = charging; + } + + [DBus (visible = false)] + public void bus_register (DBusConnection conn, string path) throws IOError { + if (this.register_id == 0) + this.register_id = conn.register_object (path, this); + + this.prop_notifier = new DBusPropertyNotifier (conn, + "org.mconnect.Device.Battery", + path); + + this.notify.connect (this.send_property_change); + } + + [DBus (visible = false)] + public void bus_unregister (DBusConnection conn) throws IOError { + if (this.register_id != 0) + conn.unregister_object (this.register_id); + this.register_id = 0; + + this.notify.disconnect (this.send_property_change); + this.notify_id = 0; + } + + private void send_property_change (ParamSpec p) { + assert (this.prop_notifier != null); + + Variant v = null; + + if (p.name == "level") { + v = this.level; + } + if (p.name == "charging") { + v = this.charging; + } + + if (v == null) + return; + + this.prop_notifier.queue_property_change (p.name, v); + } } \ No newline at end of file diff --git a/src/mconnect/battery.vala b/src/mconnect/battery.vala index 1407065..69c13e8 100644 --- a/src/mconnect/battery.vala +++ b/src/mconnect/battery.vala @@ -20,44 +20,43 @@ class BatteryHandler : Object, PacketHandlerInterface { - public const string BATTERY = "kdeconnect.battery"; + public const string BATTERY = "kdeconnect.battery"; - public string get_pkt_type() { - return BATTERY; - } + public string get_pkt_type () { + return BATTERY; + } - private BatteryHandler() { + private BatteryHandler () { + } - } + public static BatteryHandler instance () { + return new BatteryHandler (); + } - public static BatteryHandler instance() { - return new BatteryHandler(); - } + public void use_device (Device dev) { + debug ("use device %s for battery status updates", dev.to_string ()); + dev.message.connect (this.message); + } - public void use_device(Device dev) { - debug("use device %s for battery status updates", dev.to_string()); - dev.message.connect(this.message); - } + public void release_device (Device dev) { + debug ("release device %s", dev.to_string ()); + dev.message.disconnect (this.message); + } - public void release_device(Device dev) { - debug("release device %s", dev.to_string()); - dev.message.disconnect(this.message); - } + public void message (Device dev, Packet pkt) { + if (pkt.pkt_type != BATTERY) { + return; + } - public void message(Device dev, Packet pkt) { - if (pkt.pkt_type != BATTERY) { - return; - } + debug ("got battery packet"); - debug("got battery packet"); + int64 level = pkt.body.get_int_member ("currentCharge"); + bool charging = pkt.body.get_boolean_member ("isCharging"); - int64 level = pkt.body.get_int_member("currentCharge"); - bool charging = pkt.body.get_boolean_member("isCharging"); + debug ("battery level: %u %s", (uint) level, + (charging == true) ? "charging" : ""); + battery (dev, (uint) level, charging); + } - debug("battery level: %u %s", (uint) level, - (charging == true) ? "charging" : ""); - battery(dev, (uint)level, charging); - } - - public signal void battery(Device dev, uint level, bool charging); + public signal void battery (Device dev, uint level, bool charging); } \ No newline at end of file diff --git a/src/mconnect/config.vala b/src/mconnect/config.vala index 0a36650..eae32fd 100644 --- a/src/mconnect/config.vala +++ b/src/mconnect/config.vala @@ -19,98 +19,99 @@ */ public class Config : Object { - public const string FILE = "mconnect.conf"; - - private KeyFile _kf = null; - - public string path { get; private set; default = null; } - - public static string[] config_search_dirs(string primary_dir) { - string[] dirs = {primary_dir}; - - string[] sysdirs = Environment.get_system_data_dirs(); - foreach (string d in sysdirs) { - dirs += Path.build_path(Path.DIR_SEPARATOR_S, - d, "mconnect"); - } - return dirs; - } - - public Config(string base_config_dir) { - - _kf = new KeyFile(); - string[] dirs = config_search_dirs(base_config_dir); - string full_path = null; - - foreach (string d in dirs) { - debug("config search dir: %s", d); - } - - try { - bool found = _kf.load_from_dirs(Config.FILE, dirs, - out full_path, - KeyFileFlags.KEEP_COMMENTS); - path = full_path; - if (found == false) { - critical("configuration file %s was not found", - Config.FILE); - } - message("loaded configuration from %s", full_path); - } catch (KeyFileError ke) { - critical("failed to parse configuration file: %s", ke.message); - } catch (FileError fe) { - critical("failed to read configuration file: %s", fe.message); - } - } - - public void dump_to_file(string path) { - if (_kf == null) - return; - - string data = _kf.to_data(); - try { - FileUtils.set_contents(path, data); - } catch (FileError e) { - critical("failed to save configuration to %s: %s", - path, e.message); - } - } - - public bool is_device_allowed(string name, string type) { - - debug("check if device %s type %s is allowed", name, type); - try { - string[] devices = _kf.get_string_list("main", "devices"); - - foreach (string dev in devices) { - debug("checking dev %s", dev); - // - if (_kf.has_group(dev) == false) { - debug("no group %s", dev); - continue; - } - - if (_kf.get_string(dev, "name") == name && - _kf.get_string(dev, "type") == type && - _kf.get_boolean(dev, "allowed") == true) - { - return true; - } - } - } catch (KeyFileError ke) { - critical("failed to read entries from configuration file: %s", - ke.message); - } - return false; - } - - public bool is_debug_on() { - try { - bool debug = _kf.get_boolean("main", "debug"); - return debug; - } catch (KeyFileError ke) { - critical("failed to read config entry"); - } - return false; - } + public const string FILE = "mconnect.conf"; + + private KeyFile _kf = null; + + public string path { + get; private set; default = null; + } + + public static string[] config_search_dirs (string primary_dir) { + string[] dirs = { primary_dir }; + + string[] sysdirs = Environment.get_system_data_dirs (); + foreach (string d in sysdirs) { + dirs += Path.build_path (Path.DIR_SEPARATOR_S, + d, "mconnect"); + } + return dirs; + } + + public Config (string base_config_dir) { + + _kf = new KeyFile (); + string[] dirs = config_search_dirs (base_config_dir); + string full_path = null; + + foreach (string d in dirs) { + debug ("config search dir: %s", d); + } + + try { + bool found = _kf.load_from_dirs (Config.FILE, dirs, + out full_path, + KeyFileFlags.KEEP_COMMENTS); + path = full_path; + if (found == false) { + critical ("configuration file %s was not found", + Config.FILE); + } + message ("loaded configuration from %s", full_path); + } catch (KeyFileError ke) { + critical ("failed to parse configuration file: %s", ke.message); + } catch (FileError fe) { + critical ("failed to read configuration file: %s", fe.message); + } + } + + public void dump_to_file (string path) { + if (_kf == null) + return; + + string data = _kf.to_data (); + try { + FileUtils.set_contents (path, data); + } catch (FileError e) { + critical ("failed to save configuration to %s: %s", + path, e.message); + } + } + + public bool is_device_allowed (string name, string type) { + + debug ("check if device %s type %s is allowed", name, type); + try { + string[] devices = _kf.get_string_list ("main", "devices"); + + foreach (string dev in devices) { + debug ("checking dev %s", dev); + // + if (_kf.has_group (dev) == false) { + debug ("no group %s", dev); + continue; + } + + if (_kf.get_string (dev, "name") == name && + _kf.get_string (dev, "type") == type && + _kf.get_boolean (dev, "allowed") == true) { + return true; + } + } + } catch (KeyFileError ke) { + critical ("failed to read entries from configuration file: %s", + ke.message); + } + return false; + } + + public bool is_debug_on () { + try { + bool debug = _kf.get_boolean ("main", "debug"); + return debug; + } catch (KeyFileError ke) { + critical ("failed to read config entry"); + } + return false; + } } \ No newline at end of file diff --git a/src/mconnect/core.vala b/src/mconnect/core.vala index 07df9af..b3bdc53 100644 --- a/src/mconnect/core.vala +++ b/src/mconnect/core.vala @@ -21,103 +21,110 @@ using Mconn; class Core : Object { - public const string APP_NAME = "mconnect"; - - public TlsCertificate certificate { get; private set; } - - public PacketHandlers handlers {get; private set; default = null; } - - public Config config { get; private set; default = null; } - - public TransferManager transfer_manager { get; set; default = null; } - - private static Core _instance = null; - - private Core() { - debug("init core"); - } - - public static Core? instance() { - if (Core._instance == null) - { - init_user_dirs(); - - var config = init_config(); - var cert = init_crypto(); - var handlers = new PacketHandlers(); - - var core = new Core(); - core.config = config; - core.certificate = cert; - core.handlers = handlers; - - info("supported interfaces: %s", - string.joinv(", ", handlers.interfaces)); - Core._instance = core; - } - - return Core._instance; - } - - public static string get_storage_dir() { - return Path.build_filename(Environment.get_user_data_dir(), - APP_NAME); - } - - public static string get_config_dir() { - return Path.build_filename(Environment.get_user_config_dir(), - APP_NAME); - } - - public static string get_cache_dir() { - return Path.build_filename(Environment.get_user_cache_dir(), - APP_NAME); - } - - private static void init_user_dirs() { - DirUtils.create_with_parents(get_storage_dir(), 0700); - DirUtils.create_with_parents(get_config_dir(), 0700); - } - - private static TlsCertificate init_crypto() throws Error { - var key_file = File.new_for_path(Path.build_filename(get_storage_dir(), - "private.pem")); - var cert_file = File.new_for_path(Path.build_filename(get_storage_dir(), - "certificate.pem")); - if (key_file.query_exists() == false || cert_file.query_exists() == false) { - try { - string host_name = Environment.get_host_name(); - string user = Environment.get_user_name(); - Crypt.generate_key_cert(key_file.get_path(), - cert_file.get_path(), - @"$user@$host_name"); - } catch (Error e) { - warning("failed to generate private key or certificate: %s", e.message); - throw e; - } - } - - TlsCertificate tls_cert; - try { - tls_cert = new TlsCertificate.from_files(cert_file.get_path(), - key_file.get_path()); - } catch (Error e) { - warning("failed to load certificate or key: %s", e.message); - throw e; - } - return tls_cert; - } - - private static Config init_config() { - string user_config_path = get_config_dir() + "/" + Config.FILE; - - var config = new Config(get_config_dir()); - - // write configuration to user config file if none is present - if (config.path != user_config_path) { - config.dump_to_file(user_config_path); - } - - return config; - } + public const string APP_NAME = "mconnect"; + + public TlsCertificate certificate { + get; private set; + } + + public PacketHandlers handlers { + get; private set; default = null; + } + + public Config config { + get; private set; default = null; + } + + public TransferManager transfer_manager { + get; set; default = null; + } + + private static Core _instance = null; + + private Core () { + debug ("init core"); + } + + public static Core ? instance () { + if (Core._instance == null) { + init_user_dirs (); + + var config = init_config (); + var cert = init_crypto (); + var handlers = new PacketHandlers (); + + var core = new Core (); + core.config = config; + core.certificate = cert; + core.handlers = handlers; + + info ("supported interfaces: %s", + string.joinv (", ", handlers.interfaces)); + Core._instance = core; + } + + return Core._instance; + } + + public static string get_storage_dir () { + return Path.build_filename (Environment.get_user_data_dir (), + APP_NAME); + } + + public static string get_config_dir () { + return Path.build_filename (Environment.get_user_config_dir (), + APP_NAME); + } + + public static string get_cache_dir () { + return Path.build_filename (Environment.get_user_cache_dir (), + APP_NAME); + } + + private static void init_user_dirs () { + DirUtils.create_with_parents (get_storage_dir (), 0700); + DirUtils.create_with_parents (get_config_dir (), 0700); + } + + private static TlsCertificate init_crypto () throws Error { + var key_file = File.new_for_path (Path.build_filename (get_storage_dir (), + "private.pem")); + var cert_file = File.new_for_path (Path.build_filename (get_storage_dir (), + "certificate.pem")); + if (key_file.query_exists () == false || cert_file.query_exists () == false) { + try { + string host_name = Environment.get_host_name (); + string user = Environment.get_user_name (); + Crypt.generate_key_cert (key_file.get_path (), + cert_file.get_path (), + @"$user@$host_name"); + } catch (Error e) { + warning ("failed to generate private key or certificate: %s", e.message); + throw e; + } + } + + TlsCertificate tls_cert; + try { + tls_cert = new TlsCertificate.from_files (cert_file.get_path (), + key_file.get_path ()); + } catch (Error e) { + warning ("failed to load certificate or key: %s", e.message); + throw e; + } + return tls_cert; + } + + private static Config init_config () { + string user_config_path = get_config_dir () + "/" + Config.FILE; + + var config = new Config (get_config_dir ()); + + // write configuration to user config file if none is present + if (config.path != user_config_path) { + config.dump_to_file (user_config_path); + } + + return config; + } } \ No newline at end of file diff --git a/src/mconnect/device-proxy.vala b/src/mconnect/device-proxy.vala index 2fd6a16..1668666 100644 --- a/src/mconnect/device-proxy.vala +++ b/src/mconnect/device-proxy.vala @@ -26,233 +26,264 @@ using Gee; [DBus (name = "org.mconnect.Device")] class DeviceDBusProxy : Object { - public string id { - get { return device.device_id; } - private set {} - default = ""; - } - public string name { - get { return device.device_name; } - private set {} - default = ""; - } - public string device_type { - get { return device.device_type; } - private set {} - default = ""; - } - public uint protocol_version { - get { return device.protocol_version; } - private set {} - default = 5; - } - public string address { get; private set; default = ""; } - - public bool is_paired { - get { return device.is_paired; } - private set {} - default = false; - } - public bool allowed { - get { return device.allowed; } - private set {} - default = false; - } - public bool is_active { - get { return device.is_active; } - private set {} - default = false; - } - public bool is_connected { get; private set; default = false; } - - public string[] incoming_capabilities { - get; - private set; - } - - public string[] outgoing_capabilities { - get; - private set; - } - - public string certificate { - owned get { return device.certificate_pem; } - private set {} - } - - public string certificate_fingerprint { - get { return device.certificate_fingerprint; } - private set {} - } - - private HashMap handlers; - - private uint register_id = 0; - - private DBusPropertyNotifier prop_notifier = null; - - [DBus (visible = false)] - public ObjectPath object_path = null; - - [DBus (visible = false)] - public Device device {get; private set; default = null; } - - public DeviceDBusProxy.for_device_with_path(Device device, ObjectPath path) { - this.device = device; - this.object_path = path; - this.handlers = new HashMap(); - this.update_address(); - this.update_capabilities(); - this.device.notify.connect(this.param_changed); - this.device.connected.connect(() => { - this.is_connected = true; - }); - this.device.disconnected.connect(() => { - this.is_connected = false; - }); - this.notify.connect(this.update_properties); - } - - private void update_capabilities() { - string[] caps = {}; - - foreach (var cap in device.incoming_capabilities) { - caps += cap; - } - this.incoming_capabilities = caps; - - caps = {}; - - foreach (var cap in device.outgoing_capabilities) { - caps += cap; - } - this.outgoing_capabilities = caps; - } - - private void update_address() { - this.address = "%s:%u".printf(device.host.to_string(), - device.tcp_port); - } - - private void update_properties(ParamSpec param) { - debug("param %s changed", param.name); - - string name = param.name; - Variant v = null; - switch (param.name) { - case "address": - v = this.address; - break; - case "id": - v = this.id; - break; - case "name": - v = this.name; - break; - case "device-type": - name = "DeviceType"; - v = this.device_type; - break; - case "potocol-version": - name = "ProtocolVersion"; - v = this.protocol_version; - break; - case "is-paired": - name = "IsPaired"; - v = this.is_paired; - break; - case "allowed": - v = this.allowed; - break; - case "is-active": - name = "IsActive"; - v = this.is_active; - break; - case "is-connected": - name = "IsConnected"; - v = this.is_connected; - break; - case "certificate": - name = "certificate"; - v = this.certificate; - break; - } - - if (v == null) - return; - - this.prop_notifier.queue_property_change(name, v); - } - - private void param_changed(ParamSpec param) { - debug("parameter %s changed", param.name); - switch (param.name) { - case "host": - case "tcp-port": - this.update_address(); - break; - case "allowed": - this.allowed = device.allowed; - break; - case "is-active": - this.is_active = device.is_active; - break; - case "is-paired": - this.is_paired = device.is_paired; - break; - case "incoming-capabilities": - case "outgoing-capabilities": - this.update_capabilities(); - break; - } - } - - [DBus (visible = false)] - public bool has_handler(string cap) { - return this.handlers.has_key(cap); - } - - [DBus (visible = false)] - public void bus_register(DBusConnection conn) { - try { - this.register_id = conn.register_object(this.object_path, this); - this.prop_notifier = new DBusPropertyNotifier(conn, - "org.mconnect.Device", - this.object_path); - } catch (IOError err) { - warning("failed to register DBus object for device %s under path %s", - this.device.to_string(), this.object_path.to_string()); - } - } - - [DBus (visible = false)] - public void bus_unregister(DBusConnection conn) { - if (this.register_id != 0) { - conn.unregister_object(this.register_id); - } - this.register_id = 0; - this.prop_notifier = null; - } - - [DBus (visible = false)] - public void bus_register_handler(DBusConnection conn, - string cap, - PacketHandlerInterfaceProxy handler) { - - handler.bus_register(conn, this.object_path); - this.handlers.@set(cap, handler); - } - - [DBus (visible = false)] - public void bus_unregister_handler(DBusConnection conn, - string cap) { - PacketHandlerInterfaceProxy handler; - - this.handlers.@unset(cap, out handler); - if (handler != null) { - handler.bus_unregister(conn); - } - } - - + public string id { + get { + return device.device_id; + } + private set { + } + default = ""; + } + public string name { + get { + return device.device_name; + } + private set { + } + default = ""; + } + public string device_type { + get { + return device.device_type; + } + private set { + } + default = ""; + } + public uint protocol_version { + get { + return device.protocol_version; + } + private set { + } + default = 5; + } + public string address { + get; private set; default = ""; + } + + public bool is_paired { + get { + return device.is_paired; + } + private set { + } + default = false; + } + public bool allowed { + get { + return device.allowed; + } + private set { + } + default = false; + } + public bool is_active { + get { + return device.is_active; + } + private set { + } + default = false; + } + public bool is_connected { + get; private set; default = false; + } + + public string[] incoming_capabilities { + get; + private set; + } + + public string[] outgoing_capabilities { + get; + private set; + } + + public string certificate { + owned get { + return device.certificate_pem; + } + private set { + } + } + + public string certificate_fingerprint { + get { + return device.certificate_fingerprint; + } + private set { + } + } + + private HashMap handlers; + + private uint register_id = 0; + + private DBusPropertyNotifier prop_notifier = null; + + [DBus (visible = false)] + public ObjectPath object_path = null; + + [DBus (visible = false)] + public Device device { + get; private set; default = null; + } + + public DeviceDBusProxy.for_device_with_path (Device device, ObjectPath path) { + this.device = device; + this.object_path = path; + this.handlers = new HashMap(); + this.update_address (); + this.update_capabilities (); + this.device.notify.connect (this.param_changed); + this.device.connected.connect (() => { + this.is_connected = true; + }); + this.device.disconnected.connect (() => { + this.is_connected = false; + }); + this.notify.connect (this.update_properties); + } + + private void update_capabilities () { + string[] caps = {}; + + foreach (var cap in device.incoming_capabilities) { + caps += cap; + } + this.incoming_capabilities = caps; + + caps = {}; + + foreach (var cap in device.outgoing_capabilities) { + caps += cap; + } + this.outgoing_capabilities = caps; + } + + private void update_address () { + this.address = "%s:%u".printf (device.host.to_string (), + device.tcp_port); + } + + private void update_properties (ParamSpec param) { + debug ("param %s changed", param.name); + + string name = param.name; + Variant v = null; + switch (param.name) { + case "address": + v = this.address; + break; + case "id": + v = this.id; + break; + case "name": + v = this.name; + break; + case "device-type": + name = "DeviceType"; + v = this.device_type; + break; + case "potocol-version": + name = "ProtocolVersion"; + v = this.protocol_version; + break; + case "is-paired": + name = "IsPaired"; + v = this.is_paired; + break; + case "allowed": + v = this.allowed; + break; + case "is-active": + name = "IsActive"; + v = this.is_active; + break; + case "is-connected": + name = "IsConnected"; + v = this.is_connected; + break; + case "certificate": + name = "certificate"; + v = this.certificate; + break; + } + + if (v == null) + return; + + this.prop_notifier.queue_property_change (name, v); + } + + private void param_changed (ParamSpec param) { + debug ("parameter %s changed", param.name); + switch (param.name) { + case "host": + case "tcp-port": + this.update_address (); + break; + case "allowed": + this.allowed = device.allowed; + break; + case "is-active": + this.is_active = device.is_active; + break; + case "is-paired": + this.is_paired = device.is_paired; + break; + case "incoming-capabilities": + case "outgoing-capabilities": + this.update_capabilities (); + break; + } + } + + [DBus (visible = false)] + public bool has_handler (string cap) { + return this.handlers.has_key (cap); + } + + [DBus (visible = false)] + public void bus_register (DBusConnection conn) { + try { + this.register_id = conn.register_object (this.object_path, this); + this.prop_notifier = new DBusPropertyNotifier (conn, + "org.mconnect.Device", + this.object_path); + } catch (IOError err) { + warning ("failed to register DBus object for device %s under path %s", + this.device.to_string (), this.object_path.to_string ()); + } + } + + [DBus (visible = false)] + public void bus_unregister (DBusConnection conn) { + if (this.register_id != 0) { + conn.unregister_object (this.register_id); + } + this.register_id = 0; + this.prop_notifier = null; + } + + [DBus (visible = false)] + public void bus_register_handler (DBusConnection conn, + string cap, + PacketHandlerInterfaceProxy handler) { + + handler.bus_register (conn, this.object_path); + this.handlers.@set (cap, handler); + } + + [DBus (visible = false)] + public void bus_unregister_handler (DBusConnection conn, + string cap) { + PacketHandlerInterfaceProxy handler; + + this.handlers.@unset (cap, out handler); + if (handler != null) { + handler.bus_unregister (conn); + } + } } \ No newline at end of file diff --git a/src/mconnect/device.vala b/src/mconnect/device.vala index 12b04a2..1743058 100644 --- a/src/mconnect/device.vala +++ b/src/mconnect/device.vala @@ -26,577 +26,600 @@ using Mconn; */ class Device : Object { - public const uint PAIR_TIMEOUT = 30; - - public signal void paired(bool pair); - public signal void connected(); - public signal void disconnected(); - public signal void message(Packet pkt); - /** - * capability_added: - * @cap: device capability, eg. kdeconnect.notification - * - * Device capability was added - */ - public signal void capability_added(string cap); - /** - * capability_removed: - * @cap: device capability, eg. kdeconnect.notification - * - * Device capability was removed - */ - public signal void capability_removed(string cap); - - public string device_id { get; private set; default = ""; } - public string device_name { get; private set; default = ""; } - public string device_type { get; private set; default = ""; } - public uint protocol_version {get; private set; default = 7; } - public uint tcp_port {get; private set; default = 1714; } - public InetAddress host { get; private set; default = null; } - public bool is_paired { get; private set; default = false; } - public bool allowed {get; set; default = false; } - public bool is_active { get; private set; default = false; } - - public ArrayList outgoing_capabilities { - get; - private set; - default = null; - } - public ArrayList incoming_capabilities { - get; - private set; - default = null; - } - private HashSet _capabilities = null; - - public TlsCertificate certificate = null; - public string certificate_pem { owned get { - if (this.certificate == null) { - return ""; - } - return this.certificate.certificate_pem; - } - private set {} - } - public string certificate_fingerprint { get; private set; default = ""; } - - // set to true if pair request was sent - private bool _pair_in_progress = false; - private uint _pair_timeout_source = 0; - - private DeviceChannel _channel = null; - - // registered packet handlers - private HashMap _handlers; - - private Device() { - incoming_capabilities = new ArrayList(); - outgoing_capabilities = new ArrayList(); - _capabilities = new HashSet(); - _handlers = new HashMap(); - } - - /** - * Constructs a new Device wrapper based on identity packet. - * - * @param pkt identity packet - * @param host source host that the packet came from - */ - public Device.from_discovered_device(DiscoveredDevice disc) { - this(); - - this.host = disc.host; - this.device_name = disc.device_name; - this.device_id = disc.device_id; - this.device_type = disc.device_type; - this.protocol_version = disc.protocol_version; - this.tcp_port = disc.tcp_port; - this.outgoing_capabilities = new ArrayList.wrap( - disc.outgoing_capabilities); - this.incoming_capabilities = new ArrayList.wrap( - disc.incoming_capabilities); - - debug("new device: %s", this.to_string()); - } - - /** - * Constructs a new Device wrapper based on data read from device - * cache file. - * - * @cache: device cache file - * @name: device name - */ - public static Device? new_from_cache(KeyFile cache, string name) { - debug("device from cache group %s", name); - - try { - var dev = new Device(); - dev.device_id = cache.get_string(name, "deviceId"); - dev.device_name = cache.get_string(name, "deviceName"); - dev.device_type = cache.get_string(name, "deviceType"); - dev.protocol_version = cache.get_integer(name, "protocolVersion"); - dev.tcp_port = (uint) cache.get_integer(name, "tcpPort"); - var last_ip_str = cache.get_string(name, "lastIPAddress"); - debug("last known address: %s:%u", last_ip_str, dev.tcp_port); - dev.allowed = cache.get_boolean(name, "allowed"); - dev.is_paired = cache.get_boolean(name, "paired"); - try { - var cached_certificate = cache.get_string(name, "certificate"); - if (cached_certificate != "") { - var cert = new TlsCertificate.from_pem(cached_certificate, - cached_certificate.length); - dev.update_certificate(cert); - } - } catch (KeyFileError e) { - if (e is KeyFileError.KEY_NOT_FOUND) { - warning("device %s using older cache format", - dev.device_id); - } else { - throw e; - } - } - dev.outgoing_capabilities = new ArrayList.wrap( - cache.get_string_list(name, - "outgoing_capabilities")); - dev.incoming_capabilities = new ArrayList.wrap( - cache.get_string_list(name, - "incoming_capabilities")); - - var host = new InetAddress.from_string(last_ip_str); - if (host == null) { - debug("failed to parse last known IP address (%s) for device %s", - last_ip_str, name); - return null; - } - dev.host = host; - - return dev; - } - catch (KeyFileError e) { - warning("failed to load device data from cache: %s", e.message); - return null; - } - } - - ~Device() { - - } - - /** - * Generates a unique string for this device - */ - public string to_unique_string() { - return Utils.make_unique_device_string(this.device_id, - this.device_name, - this.device_type, - this.protocol_version); - } - - public string to_string() { - return Utils.make_device_string(this.device_id, - this.device_name, - this.device_type, - this.protocol_version); - } - - /** - * Dump device information to cache - * - * @cache: device cache - * @name: group name - */ - public void to_cache(KeyFile cache, string name) { - cache.set_string(name, "deviceId", this.device_id); - cache.set_string(name, "deviceName", this.device_name); - cache.set_string(name, "deviceType", this.device_type); - cache.set_integer(name, "protocolVersion", (int) this.protocol_version); - cache.set_integer(name, "tcpPort", (int) this.tcp_port); - cache.set_string(name, "lastIPAddress", this.host.to_string()); - cache.set_boolean(name, "allowed", this.allowed); - cache.set_boolean(name, "paired", this.is_paired); - cache.set_string(name, "certificate", this.certificate_pem); - cache.set_string_list(name, "outgoing_capabilities", - this.outgoing_capabilities.to_array()); - cache.set_string_list(name, "incoming_capabilities", - this.incoming_capabilities.to_array()); - } - - private async void greet() { - var core = Core.instance(); - string host_name = Environment.get_host_name(); - string user = Environment.get_user_name(); - yield _channel.send(Packet.new_identity(@"$user@$host_name", - Environment.get_host_name(), - core.handlers.interfaces, - core.handlers.interfaces)); - - // switch to secure channel - var secure = yield _channel.secure(this.certificate); - info("secure: %s", secure.to_string()); - - if (secure) { - this.update_certificate(_channel.peer_certificate); - - this.maybe_pair(); - } else { - warning("failed to enable secure channel"); - close_and_cleanup(); - } - } - - /** - * pair: sent pair request - * - * Internally changes pair requests state tracking. - * - * @param expect_response se to true if expecting a response - */ - public async void pair(bool expect_response = true) { - if (this.host != null) { - debug("start pairing"); - - if (expect_response == true) { - _pair_in_progress = true; - // pairing timeout - _pair_timeout_source = Timeout.add_seconds(PAIR_TIMEOUT, - this.pair_timeout); - } - // send request - yield _channel.send(Packet.new_pair()); - } - } - - private bool pair_timeout() { - warning("pair request timeout"); - - _pair_timeout_source = 0; - - // handle failed pairing - handle_pair(false); - - // remove timeout source - return false; - } - - /** - * maybe_pair: - * - * Trigger pairing or call handle_pair() if already paired. - */ - public void maybe_pair() { - if (is_paired == false) { - if (_pair_in_progress == false) - this.pair.begin(); - } else { - // we are already paired - handle_pair(true); - } - } - - /** - * activate: - * - * Activate device. Triggers sending of #paired signal after - * successfuly opening a connection. - */ - public void activate() { - if (_channel != null) { - debug("device %s already active", this.to_string()); - } - - _channel = new DeviceChannel(this.host, this.tcp_port); - _channel.disconnected.connect((c) => { - this.handle_disconnect(); - }); - _channel.packet_received.connect((c, pkt) => { - this.packet_received(pkt); - }); - _channel.open.begin((c, res) => { - this.channel_openend(_channel.open.end(res)); - }); - - this.is_active = true; - } - - /** - * deactivate: - * - * Deactivate device - */ - public void deactivate() { - if (_channel != null) { - close_and_cleanup(); - } - } + public const uint PAIR_TIMEOUT = 30; + + public signal void paired (bool pair); + public signal void connected (); + public signal void disconnected (); + public signal void message (Packet pkt); + + /** + * capability_added: + * @cap: device capability, eg. kdeconnect.notification + * + * Device capability was added + */ + public signal void capability_added (string cap); + + /** + * capability_removed: + * @cap: device capability, eg. kdeconnect.notification + * + * Device capability was removed + */ + public signal void capability_removed (string cap); + + public string device_id { + get; private set; default = ""; + } + public string device_name { + get; private set; default = ""; + } + public string device_type { + get; private set; default = ""; + } + public uint protocol_version { + get; private set; default = 7; + } + public uint tcp_port { + get; private set; default = 1714; + } + public InetAddress host { + get; private set; default = null; + } + public bool is_paired { + get; private set; default = false; + } + public bool allowed { + get; set; default = false; + } + public bool is_active { + get; private set; default = false; + } + + public ArrayList outgoing_capabilities { + get; + private set; + default = null; + } + public ArrayList incoming_capabilities { + get; + private set; + default = null; + } + private HashSet _capabilities = null; + + public TlsCertificate certificate = null; + public string certificate_pem { + owned get { + if (this.certificate == null) { + return ""; + } + return this.certificate.certificate_pem; + } + private set { + } + } + public string certificate_fingerprint { + get; private set; default = ""; + } + + // set to true if pair request was sent + private bool _pair_in_progress = false; + private uint _pair_timeout_source = 0; + + private DeviceChannel _channel = null; + + // registered packet handlers + private HashMap _handlers; + + private Device () { + incoming_capabilities = new ArrayList(); + outgoing_capabilities = new ArrayList(); + _capabilities = new HashSet(); + _handlers = new HashMap(); + } + + /** + * Constructs a new Device wrapper based on identity packet. + * + * @param pkt identity packet + * @param host source host that the packet came from + */ + public Device.from_discovered_device (DiscoveredDevice disc) { + this(); + + this.host = disc.host; + this.device_name = disc.device_name; + this.device_id = disc.device_id; + this.device_type = disc.device_type; + this.protocol_version = disc.protocol_version; + this.tcp_port = disc.tcp_port; + this.outgoing_capabilities = new ArrayList.wrap ( + disc.outgoing_capabilities); + this.incoming_capabilities = new ArrayList.wrap ( + disc.incoming_capabilities); + + debug ("new device: %s", this.to_string ()); + } + + /** + * Constructs a new Device wrapper based on data read from device + * cache file. + * + * @cache: device cache file + * @name: device name + */ + public static Device ? new_from_cache (KeyFile cache, string name) { + debug ("device from cache group %s", name); + + try { + var dev = new Device (); + dev.device_id = cache.get_string (name, "deviceId"); + dev.device_name = cache.get_string (name, "deviceName"); + dev.device_type = cache.get_string (name, "deviceType"); + dev.protocol_version = cache.get_integer (name, "protocolVersion"); + dev.tcp_port = (uint) cache.get_integer (name, "tcpPort"); + var last_ip_str = cache.get_string (name, "lastIPAddress"); + debug ("last known address: %s:%u", last_ip_str, dev.tcp_port); + dev.allowed = cache.get_boolean (name, "allowed"); + dev.is_paired = cache.get_boolean (name, "paired"); + try { + var cached_certificate = cache.get_string (name, "certificate"); + if (cached_certificate != "") { + var cert = new TlsCertificate.from_pem (cached_certificate, + cached_certificate.length); + dev.update_certificate (cert); + } + } catch (KeyFileError e) { + if (e is KeyFileError.KEY_NOT_FOUND) { + warning ("device %s using older cache format", + dev.device_id); + } else { + throw e; + } + } + dev.outgoing_capabilities = new ArrayList.wrap ( + cache.get_string_list (name, + "outgoing_capabilities")); + dev.incoming_capabilities = new ArrayList.wrap ( + cache.get_string_list (name, + "incoming_capabilities")); + + var host = new InetAddress.from_string (last_ip_str); + if (host == null) { + debug ("failed to parse last known IP address (%s) for device %s", + last_ip_str, name); + return null; + } + dev.host = host; + + return dev; + } catch (KeyFileError e) { + warning ("failed to load device data from cache: %s", e.message); + return null; + } + } + + ~Device () { + } + + /** + * Generates a unique string for this device + */ + public string to_unique_string () { + return Utils.make_unique_device_string (this.device_id, + this.device_name, + this.device_type, + this.protocol_version); + } + + public string to_string () { + return Utils.make_device_string (this.device_id, + this.device_name, + this.device_type, + this.protocol_version); + } + + /** + * Dump device information to cache + * + * @cache: device cache + * @name: group name + */ + public void to_cache (KeyFile cache, string name) { + cache.set_string (name, "deviceId", this.device_id); + cache.set_string (name, "deviceName", this.device_name); + cache.set_string (name, "deviceType", this.device_type); + cache.set_integer (name, "protocolVersion", (int) this.protocol_version); + cache.set_integer (name, "tcpPort", (int) this.tcp_port); + cache.set_string (name, "lastIPAddress", this.host.to_string ()); + cache.set_boolean (name, "allowed", this.allowed); + cache.set_boolean (name, "paired", this.is_paired); + cache.set_string (name, "certificate", this.certificate_pem); + cache.set_string_list (name, "outgoing_capabilities", + this.outgoing_capabilities.to_array ()); + cache.set_string_list (name, "incoming_capabilities", + this.incoming_capabilities.to_array ()); + } + + private async void greet () { + var core = Core.instance (); + string host_name = Environment.get_host_name (); + string user = Environment.get_user_name (); + yield _channel.send (Packet.new_identity (@"$user@$host_name", + Environment.get_host_name (), + core.handlers.interfaces, + core.handlers.interfaces)); + + // switch to secure channel + var secure = yield _channel.secure (this.certificate); + + info ("secure: %s", secure.to_string ()); + + if (secure) { + this.update_certificate (_channel.peer_certificate); + + this.maybe_pair (); + } else { + warning ("failed to enable secure channel"); + close_and_cleanup (); + } + } + + /** + * pair: sent pair request + * + * Internally changes pair requests state tracking. + * + * @param expect_response se to true if expecting a response + */ + public async void pair (bool expect_response = true) { + if (this.host != null) { + debug ("start pairing"); + + if (expect_response == true) { + _pair_in_progress = true; + // pairing timeout + _pair_timeout_source = Timeout.add_seconds (PAIR_TIMEOUT, + this.pair_timeout); + } + // send request + yield _channel.send (Packet.new_pair ()); + } + } + + private bool pair_timeout () { + warning ("pair request timeout"); + + _pair_timeout_source = 0; + + // handle failed pairing + handle_pair (false); + + // remove timeout source + return false; + } + + /** + * maybe_pair: + * + * Trigger pairing or call handle_pair() if already paired. + */ + public void maybe_pair () { + if (is_paired == false) { + if (_pair_in_progress == false) + this.pair.begin (); + } else { + // we are already paired + handle_pair (true); + } + } + + /** + * activate: + * + * Activate device. Triggers sending of #paired signal after + * successfuly opening a connection. + */ + public void activate () { + if (_channel != null) { + debug ("device %s already active", this.to_string ()); + } + + _channel = new DeviceChannel (this.host, this.tcp_port); + _channel.disconnected.connect ((c) => { + this.handle_disconnect (); + }); + _channel.packet_received.connect ((c, pkt) => { + this.packet_received (pkt); + }); + _channel.open.begin ((c, res) => { + this.channel_openend (_channel.open.end (res)); + }); + + this.is_active = true; + } + + /** + * deactivate: + * + * Deactivate device + */ + public void deactivate () { + if (_channel != null) { + close_and_cleanup (); + } + } + + /** + * channel_openend: + * + * Callback after DeviceChannel.open() has completed. If the + * channel was successfuly opened, proceed with handshake. + */ + private void channel_openend (bool result) { + debug ("channel openend: %s", result.to_string ()); + + connected (); + + if (result == true) { + greet.begin (); + } else { + // failed to open channel, invoke cleanup + channel_closed_cleanup (); + } + } + + private void packet_received (Packet pkt) { + vdebug ("got packet"); + if (pkt.pkt_type == Packet.PAIR) { + // pairing + handle_pair_packet (pkt); + } else { + // we sent a pair request, but got another packet, + // supposedly meaning we're alredy paired since the device + // is sending us data + if (this.is_paired == false) { + warning ("not paired and still got a packet, " + + "assuming device is paired", + Packet.PAIR); + handle_pair (true); + } + + // emit signal + message (pkt); + } + } + + /** + * handle_pair_packet: + * + * Handle incoming packet of Packet.PAIR type. Inside, try to + * guess if we got a response for a pair request, or is this an + * unsolicited pair request coming from mobile. + */ + private void handle_pair_packet (Packet pkt) { + assert (pkt.pkt_type == Packet.PAIR); + + bool pair = pkt.body.get_boolean_member ("pair"); + + handle_pair (pair); + } + + /** + * handle_pair: + * @pair: pairing status + * + * Update device pair status. + */ + private void handle_pair (bool pair) { + if (this._pair_timeout_source != 0) { + Source.remove (_pair_timeout_source); + this._pair_timeout_source = 0; + } + + debug ("pair in progress: %s is paired: %s pair: %s", + _pair_in_progress.to_string (), this.is_paired.to_string (), + pair.to_string ()); + if (_pair_in_progress == true) { + // response to host initiated pairing + if (pair == true) { + debug ("device is paired, pairing complete"); + this.is_paired = true; + } else { + warning ("pairing rejected by device"); + this.is_paired = false; + } + // pair completed + _pair_in_progress = false; + } else { + debug ("unsolicited pair change from device, pair status: %s", + pair.to_string ()); + if (pair == false) { + // unpair from device + this.is_paired = false; + } else { + // split brain, pair was not initiated by us, but we were called + // with information that we are paired, assume we are paired and + // send a pair packet, but not expecting a response this time + + this.pair.begin (false); + + this.is_paired = true; + } + } + + // emit signal + paired (is_paired); + } + + /** + * handle_disconnect: + * + * Handler for DeviceChannel.disconnected() signal + */ + private void handle_disconnect () { + // channel got disconnected + debug ("channel disconnected"); + close_and_cleanup (); + } + + private void close_and_cleanup () { + _channel.close (); + channel_closed_cleanup (); + } + + /** + * channel_closed_cleanup: + * + * Single cleanup point after channel has been closed + */ + private void channel_closed_cleanup () { + debug ("close cleanup"); + _channel = null; + + this.is_active = false; + + // emit disconnected + disconnected (); + } + + /** + * register_capability_handler: + * @cap: capability, eg. kdeconnect.notification + * @h: packet handler + * + * Keep track of capability handler @h that supports capability @cap. + * Register oneself with capability handler. + */ + public void register_capability_handler (string cap, + PacketHandlerInterface h) { + assert (this.has_capability_handler (cap) == false); + + this._handlers.@set (cap, h); + // make handler connect to device + h.use_device (this); + } + + /** + * has_capability_handler: + * @cap: capability, eg. kdeconnect.notification + * + * Returns true if there is a handler of capability @cap registed for this + * device. + */ + public bool has_capability_handler (string cap) { + return this._handlers.has_key (cap); + } + + /** + * unregister_capability_handler: + * @cap: capability, eg. kdeconnect.notification + * + * Unregisters a handler for capability @cap. + */ + private void unregister_capability_handler (string cap) { + PacketHandlerInterface handler; + this._handlers.unset (cap, out handler); + if (handler != null) { + // make handler release the device + handler.release_device (this); + } + } + + /** + * merge_capabilities: + * @added[out]: capabilities that were added + * @removed[out]: capabilities that were removed + * + * Merge and update existing `outgoing_capabilities` and + * `incoming_capabilities`. Returns lists of added and removed capabilities. + */ + private void merge_capabilities (out HashSet added, + out HashSet removed) { + + var caps = new HashSet(); + caps.add_all (this.outgoing_capabilities); + caps.add_all (this.incoming_capabilities); + + added = new HashSet(); + added.add_all (caps); + + // TODO: simplify capability names, eg kdeconnect.telephony.request -> + // kdeconnect.telephony + added.remove_all (this._capabilities); + + removed = new HashSet(); + removed.add_all (this._capabilities); + removed.remove_all (caps); + + this._capabilities = caps; + } /** - * channel_openend: - * - * Callback after DeviceChannel.open() has completed. If the - * channel was successfuly opened, proceed with handshake. - */ - private void channel_openend(bool result) { - debug("channel openend: %s", result.to_string()); - - connected(); - - if (result == true) { - greet.begin(); - } else { - // failed to open channel, invoke cleanup - channel_closed_cleanup(); - } - } - - private void packet_received(Packet pkt) { - vdebug("got packet"); - if (pkt.pkt_type == Packet.PAIR) { - // pairing - handle_pair_packet(pkt); - } else { - // we sent a pair request, but got another packet, - // supposedly meaning we're alredy paired since the device - // is sending us data - if (this.is_paired == false) { - warning("not paired and still got a packet, " + - "assuming device is paired", - Packet.PAIR); - handle_pair(true); - } - - // emit signal - message(pkt); - } - } - - /** - * handle_pair_packet: - * - * Handle incoming packet of Packet.PAIR type. Inside, try to - * guess if we got a response for a pair request, or is this an - * unsolicited pair request coming from mobile. - */ - private void handle_pair_packet(Packet pkt) { - assert(pkt.pkt_type == Packet.PAIR); - - bool pair = pkt.body.get_boolean_member("pair"); - - handle_pair(pair); - } - - /** - * handle_pair: - * @pair: pairing status - * - * Update device pair status. - */ - private void handle_pair(bool pair) { - if (this._pair_timeout_source != 0) { - Source.remove(_pair_timeout_source); - this._pair_timeout_source = 0; - } - - debug("pair in progress: %s is paired: %s pair: %s", - _pair_in_progress.to_string(), this.is_paired.to_string(), - pair.to_string()); - if (_pair_in_progress == true) { - // response to host initiated pairing - if (pair == true) { - debug("device is paired, pairing complete"); - this.is_paired = true; - } else { - warning("pairing rejected by device"); - this.is_paired = false; - } - // pair completed - _pair_in_progress = false; - } else { - debug("unsolicited pair change from device, pair status: %s", - pair.to_string()); - if (pair == false) { - // unpair from device - this.is_paired = false; - } else { - // split brain, pair was not initiated by us, but we were called - // with information that we are paired, assume we are paired and - // send a pair packet, but not expecting a response this time - - this.pair.begin(false); - - this.is_paired = true; - } - } - - // emit signal - paired(is_paired); - } - - /** - * handle_disconnect: - * - * Handler for DeviceChannel.disconnected() signal - */ - private void handle_disconnect() { - // channel got disconnected - debug("channel disconnected"); - close_and_cleanup(); - } - - private void close_and_cleanup() { - _channel.close(); - channel_closed_cleanup(); - } - - /** - * channel_closed_cleanup: - * - * Single cleanup point after channel has been closed - */ - private void channel_closed_cleanup() { - debug("close cleanup"); - _channel = null; - - this.is_active = false; - - // emit disconnected - disconnected(); - } - - /** - * register_capability_handler: - * @cap: capability, eg. kdeconnect.notification - * @h: packet handler - * - * Keep track of capability handler @h that supports capability @cap. - * Register oneself with capability handler. - */ - public void register_capability_handler(string cap, - PacketHandlerInterface h) { - assert(this.has_capability_handler(cap) == false); - - this._handlers.@set(cap, h); - // make handler connect to device - h.use_device(this); - } - - /** - * has_capability_handler: - * @cap: capability, eg. kdeconnect.notification - * - * Returns true if there is a handler of capability @cap registed for this - * device. - */ - public bool has_capability_handler(string cap) { - return this._handlers.has_key(cap); - } - - /** - * unregister_capability_handler: - * @cap: capability, eg. kdeconnect.notification - * - * Unregisters a handler for capability @cap. - */ - private void unregister_capability_handler(string cap) { - PacketHandlerInterface handler; - this._handlers.unset(cap, out handler); - if (handler != null) { - // make handler release the device - handler.release_device(this); - } - } - - /** - * merge_capabilities: - * @added[out]: capabilities that were added - * @removed[out]: capabilities that were removed - * - * Merge and update existing `outgoing_capabilities` and - * `incoming_capabilities`. Returns lists of added and removed capabilities. - */ - private void merge_capabilities(out HashSet added, - out HashSet removed) { - - var caps = new HashSet(); - caps.add_all(this.outgoing_capabilities); - caps.add_all(this.incoming_capabilities); - - added = new HashSet(); - added.add_all(caps); - - // TODO: simplify capability names, eg kdeconnect.telephony.request -> - // kdeconnect.telephony - added.remove_all(this._capabilities); - - removed = new HashSet(); - removed.add_all(this._capabilities); - removed.remove_all(caps); - - this._capabilities = caps; - } - - /** - * update_from_device: - * @other_dev: other device - * - * Update information/state of this device using data from @other_dev. This - * may happen in case when a discovery packet was received, or a device got - * connected. In such case, a `this` device (which was likely created from - * cached data) needs to be updated. - * - * As a side effect, updating capabilities will emit @capability_added - * and @capability_removed signals. - */ - public void update_from_device(Device other_dev) { - this.outgoing_capabilities = other_dev.outgoing_capabilities; - this.incoming_capabilities = other_dev.incoming_capabilities; - - HashSet added; - HashSet removed; - this.merge_capabilities(out added, out removed); - - foreach (var c in added) { - debug("added: %s", c); - capability_added(c); - } - - foreach (var c in removed) { - debug("removed: %s", c); - capability_removed(c); - // remove capability handlers - this.unregister_capability_handler(c); - } - - - if (this.host != null && this.host.to_string() != other_dev.host.to_string()) { - debug("host address changed from %s to %s", - this.host.to_string(), other_dev.host.to_string()); - // deactivate first - this.deactivate(); - - host = other_dev.host; - tcp_port = other_dev.tcp_port; - } - } - - private void update_certificate(TlsCertificate cert) { - this.certificate = cert; - - // prepare fingerprint - var fingerprint = Crypt.fingerprint_certificate(cert.certificate_pem); - var sb = new StringBuilder.sized(fingerprint.length * 2 - + "sha1:".length); - sb.append("sha1:"); - foreach(var b in fingerprint) { - sb.append_printf("%02x", b); - } - - this.certificate_fingerprint = sb.str; - } - - public void send(Packet pkt) { - // TODO: queue messages - if (this._channel != null) { - _channel.send(pkt); - } - } + * update_from_device: + * @other_dev: other device + * + * Update information/state of this device using data from @other_dev. This + * may happen in case when a discovery packet was received, or a device got + * connected. In such case, a `this` device (which was likely created from + * cached data) needs to be updated. + * + * As a side effect, updating capabilities will emit @capability_added + * and @capability_removed signals. + */ + public void update_from_device (Device other_dev) { + this.outgoing_capabilities = other_dev.outgoing_capabilities; + this.incoming_capabilities = other_dev.incoming_capabilities; + + HashSet added; + HashSet removed; + this.merge_capabilities (out added, out removed); + + foreach (var c in added) { + debug ("added: %s", c); + capability_added (c); + } + + foreach (var c in removed) { + debug ("removed: %s", c); + capability_removed (c); + // remove capability handlers + this.unregister_capability_handler (c); + } + + + if (this.host != null && this.host.to_string () != other_dev.host.to_string ()) { + debug ("host address changed from %s to %s", + this.host.to_string (), other_dev.host.to_string ()); + // deactivate first + this.deactivate (); + + host = other_dev.host; + tcp_port = other_dev.tcp_port; + } + } + + private void update_certificate (TlsCertificate cert) { + this.certificate = cert; + + // prepare fingerprint + var fingerprint = Crypt.fingerprint_certificate (cert.certificate_pem); + var sb = new StringBuilder.sized (fingerprint.length * 2 + + "sha1:".length); + sb.append ("sha1:"); + foreach (var b in fingerprint) { + sb.append_printf ("%02x", b); + } + + this.certificate_fingerprint = sb.str; + } + + public void send (Packet pkt) { + // TODO: queue messages + if (this._channel != null) { + _channel.send (pkt); + } + } } \ No newline at end of file diff --git a/src/mconnect/devicechannel.vala b/src/mconnect/devicechannel.vala index d2c80a6..6c1f85a 100644 --- a/src/mconnect/devicechannel.vala +++ b/src/mconnect/devicechannel.vala @@ -27,276 +27,277 @@ using Mconn; */ class DeviceChannel : Object { - public signal void disconnected(); - public signal void packet_received(Packet pkt); - - private InetSocketAddress _isa = null; - private SocketConnection _sock_conn = null; - private TlsConnection _tls_conn = null; - private DataOutputStream _dout = null; - private DataInputStream _din = null; - private uint _srcid = 0; - private Socket _socket = null; - - public TlsCertificate peer_certificate = null; - - public DeviceChannel(InetAddress host, uint port) { - this._isa = new InetSocketAddress(host, (uint16) port); - } - - ~DeviceChannel() { - debug("channel destroyed"); - } - - private static void fixup_socket(Socket sock) { - Utils.socket_set_keepalive(sock); - } - - private void replace_streams(InputStream input, OutputStream output) { - if (this._dout != null) { - try { - this._dout.close(); - } catch (Error e) { - warning("failed to close output stream: %s", e.message); - } - } - this._dout = new DataOutputStream(output); - - if (this._din != null) { - try { - this._din.close(); - } catch (Error e) { - warning("failed to close input stream: %s", e.message); - } - } - this._din = new DataInputStream(input); - // messages end with \n\n - this._din.set_newline_type(DataStreamNewlineType.LF); - } - - private void monitor_events() { - var source = _socket.create_source(IOCondition.IN); - source.set_callback((src, cond) => { - return this._io_ready(cond); - }); - // attach source - this._srcid = source.attach(null); - } - - private void unmonitor_events() { - if (this._srcid > 0) { - Source.remove(_srcid); - this._srcid = 0; - } - } - - public async bool open() { - GLib.assert(this._isa != null); - - debug("connect to %s:%u", this._isa.address.to_string(), this._isa.port); - - var client = new SocketClient(); - SocketConnection conn; - try { - conn = yield client.connect_async(_isa); - } catch (Error e) { - // - warning("failed to connect to %s:%u: %s", - this._isa.address.to_string(), this._isa.port, - e.message); - // emit disconnected - return false; - } - - debug("connected to %s:%u", this._isa.address.to_string(), this._isa.port); - - this._socket = conn.get_socket(); - - // fixup socket keepalive - fixup_socket(_socket); - - this._sock_conn = conn; - - // input/output streams will close underlying base stream when .close() - // is called on them, make sure that we pass Unix*Stream with which can - // skip closing the socket - this.replace_streams(new UnixInputStream(_socket.fd, false), - new UnixOutputStream(_socket.fd, false)); - - // start monitoring socket events - this.monitor_events(); - - return true; - } - - /** - * secure: - * Switch channel to TLS mode - * - * When TLS was established, `peer_certificate` will store the remote client - * certificate. If `expected_peer` is null, the peer certificate will be - * accepted unconditionally during handshake and the caller must eventually - * decide if the client is to be trusted or not. However, if `expected_peer` - * was set, the received certificate and expected one will be compared - * during handshake and connection will be rejected if a mismatch is found. - * - * @param expected_peer the peer certificate we are expecting to see - * @return true if TLS negotiation was successful, false otherwise - */ - public async bool secure(TlsCertificate? expected_peer = null) { - GLib.assert(this._sock_conn != null); - - // stop monitoring socket events - this.unmonitor_events(); - - var cert = Core.instance().certificate; - - // wrap with TLS - var tls_conn = Utils.make_tls_connection(this._sock_conn, - cert, - expected_peer); - try { - info("attempt TLS handshake"); - var res = yield tls_conn.handshake_async(); - if (res) { - info("TLS handshare successful"); - this.peer_certificate = tls_conn.peer_certificate; - } else { - warning("TLS handshake unsuccessful"); - return false; - } - } catch (Error e) { - warning("TLS handshake failed: %s", e.message); - return false; - } - - this._tls_conn = tls_conn; - // data will now pass through TLS stream wrapper - this.replace_streams(_tls_conn.input_stream, - _tls_conn.output_stream); - - // monitor socket events - this.monitor_events(); - return true; - } - - public void close() { - debug("closing connection"); - - this.unmonitor_events(); - - try { - if (this._din != null) - this._din.close(); - } catch (Error e) { - warning("failed to close data input: %s", e.message); - } - try { - if (this._dout != null) - this._dout.close(); - } catch (Error e) { - warning("failed to close data output: %s", e.message); - } - try { - if (this._tls_conn != null) - this._tls_conn.close(); - } catch (Error e) { - warning("failed to close TLS connection: %s", e.message); - } - try { - if (this._sock_conn != null) - this._sock_conn.close(); - } catch (Error e) { - warning("failed to close connection: %s", e.message); - } - this._din = null; - this._dout = null; - this._sock_conn = null; - this._tls_conn = null; - this._socket = null; - - this.peer_certificate = null; - } - - /** - * send: - * Possibly blocking - * - * @param: instance of Packet - **/ - public async void send(Packet pkt) { - string to_send = pkt.to_string() + "\n"; - debug("send data: %s", to_send); - - GLib.assert(this._dout != null); - - try { - this._dout.put_string(to_send); - } catch (IOError e) { - warning("failed to send message: %s", e.message); - // TODO disconnect? - } - } - - /** - * receive: - * Try to receive some data from channel - * - * @return false if channel was closed, true otherwise - */ - public bool receive() { - size_t line_len; - string data = null; - - GLib.assert(this._din != null); - - try { - // read line up to a newline - data = this._din.read_upto("\n", -1, out line_len, null); - - // expecting \n - this._din.read_byte(); - } catch (IOError ie) { - warning("I/O error: %s", ie.message); - } - - if (data == null) { - debug("connection closed?"); - return false; - } - - vdebug("received line: %s", data); - - Packet pkt = Packet.new_from_data(data); - if (pkt == null) { - warning("failed to build packet from data"); - // data was received, hence connection is still alive - return true; - } - - this.handle_packet(pkt); - - return true; - } - - private bool _io_ready(uint flags) { - debug("check for IO, conditions: 0x%x", flags); - bool res = this.receive(); - - if (res == false) { - // disconnected - this.disconnected(); - } - return res; - } - - private void handle_packet(Packet pkt) { - // debug("handle packet of type: %s", pkt.pkt_type); - if (pkt.pkt_type == Packet.ENCRYPTED) { - warning("received packet with eplicit encryption, this usually indicates a protocol version < 6 type packet, such pacckets are no longer supported, dropping.."); - } else { - // signal that we got a packet - this.packet_received(pkt); - } - } + public signal void disconnected (); + public signal void packet_received (Packet pkt); + + private InetSocketAddress _isa = null; + private SocketConnection _sock_conn = null; + private TlsConnection _tls_conn = null; + private DataOutputStream _dout = null; + private DataInputStream _din = null; + private uint _srcid = 0; + private Socket _socket = null; + + public TlsCertificate peer_certificate = null; + + public DeviceChannel (InetAddress host, uint port) { + this._isa = new InetSocketAddress (host, (uint16) port); + } + + ~DeviceChannel () { + debug ("channel destroyed"); + } + + private static void fixup_socket (Socket sock) { + Utils.socket_set_keepalive (sock); + } + + private void replace_streams (InputStream input, OutputStream output) { + if (this._dout != null) { + try { + this._dout.close (); + } catch (Error e) { + warning ("failed to close output stream: %s", e.message); + } + } + this._dout = new DataOutputStream (output); + + if (this._din != null) { + try { + this._din.close (); + } catch (Error e) { + warning ("failed to close input stream: %s", e.message); + } + } + this._din = new DataInputStream (input); + // messages end with \n\n + this._din.set_newline_type (DataStreamNewlineType.LF); + } + + private void monitor_events () { + var source = _socket.create_source (IOCondition.IN); + source.set_callback ((src, cond) => { + return this._io_ready (cond); + }); + // attach source + this._srcid = source.attach (null); + } + + private void unmonitor_events () { + if (this._srcid > 0) { + Source.remove (_srcid); + this._srcid = 0; + } + } + + public async bool open () { + GLib.assert (this._isa != null); + + debug ("connect to %s:%u", this._isa.address.to_string (), this._isa.port); + + var client = new SocketClient (); + SocketConnection conn; + try { + conn = yield client.connect_async (_isa); + } catch (Error e) { + // + warning ("failed to connect to %s:%u: %s", + this._isa.address.to_string (), this._isa.port, + e.message); + // emit disconnected + return false; + } + + debug ("connected to %s:%u", this._isa.address.to_string (), this._isa.port); + + this._socket = conn.get_socket (); + + // fixup socket keepalive + fixup_socket (_socket); + + this._sock_conn = conn; + + // input/output streams will close underlying base stream when .close() + // is called on them, make sure that we pass Unix*Stream with which can + // skip closing the socket + this.replace_streams (new UnixInputStream (_socket.fd, false), + new UnixOutputStream (_socket.fd, false)); + + // start monitoring socket events + this.monitor_events (); + + return true; + } + + /** + * secure: + * Switch channel to TLS mode + * + * When TLS was established, `peer_certificate` will store the remote client + * certificate. If `expected_peer` is null, the peer certificate will be + * accepted unconditionally during handshake and the caller must eventually + * decide if the client is to be trusted or not. However, if `expected_peer` + * was set, the received certificate and expected one will be compared + * during handshake and connection will be rejected if a mismatch is found. + * + * @param expected_peer the peer certificate we are expecting to see + * @return true if TLS negotiation was successful, false otherwise + */ + public async bool secure (TlsCertificate ? expected_peer = null) { + GLib.assert (this._sock_conn != null); + + // stop monitoring socket events + this.unmonitor_events (); + + var cert = Core.instance ().certificate; + + // wrap with TLS + var tls_conn = Utils.make_tls_connection (this._sock_conn, + cert, + expected_peer); + try { + info ("attempt TLS handshake"); + var res = yield tls_conn.handshake_async (); + + if (res) { + info ("TLS handshare successful"); + this.peer_certificate = tls_conn.peer_certificate; + } else { + warning ("TLS handshake unsuccessful"); + return false; + } + } catch (Error e) { + warning ("TLS handshake failed: %s", e.message); + return false; + } + + this._tls_conn = tls_conn; + // data will now pass through TLS stream wrapper + this.replace_streams (_tls_conn.input_stream, + _tls_conn.output_stream); + + // monitor socket events + this.monitor_events (); + return true; + } + + public void close () { + debug ("closing connection"); + + this.unmonitor_events (); + + try { + if (this._din != null) + this._din.close (); + } catch (Error e) { + warning ("failed to close data input: %s", e.message); + } + try { + if (this._dout != null) + this._dout.close (); + } catch (Error e) { + warning ("failed to close data output: %s", e.message); + } + try { + if (this._tls_conn != null) + this._tls_conn.close (); + } catch (Error e) { + warning ("failed to close TLS connection: %s", e.message); + } + try { + if (this._sock_conn != null) + this._sock_conn.close (); + } catch (Error e) { + warning ("failed to close connection: %s", e.message); + } + this._din = null; + this._dout = null; + this._sock_conn = null; + this._tls_conn = null; + this._socket = null; + + this.peer_certificate = null; + } + + /** + * send: + * Possibly blocking + * + * @param: instance of Packet + **/ + public async void send (Packet pkt) { + string to_send = pkt.to_string () + "\n"; + debug ("send data: %s", to_send); + + GLib.assert (this._dout != null); + + try { + this._dout.put_string (to_send); + } catch (IOError e) { + warning ("failed to send message: %s", e.message); + // TODO disconnect? + } + } + + /** + * receive: + * Try to receive some data from channel + * + * @return false if channel was closed, true otherwise + */ + public bool receive () { + size_t line_len; + string data = null; + + GLib.assert (this._din != null); + + try { + // read line up to a newline + data = this._din.read_upto ("\n", -1, out line_len, null); + + // expecting \n + this._din.read_byte (); + } catch (IOError ie) { + warning ("I/O error: %s", ie.message); + } + + if (data == null) { + debug ("connection closed?"); + return false; + } + + vdebug ("received line: %s", data); + + Packet pkt = Packet.new_from_data (data); + if (pkt == null) { + warning ("failed to build packet from data"); + // data was received, hence connection is still alive + return true; + } + + this.handle_packet (pkt); + + return true; + } + + private bool _io_ready (uint flags) { + debug ("check for IO, conditions: 0x%x", flags); + bool res = this.receive (); + + if (res == false) { + // disconnected + this.disconnected (); + } + return res; + } + + private void handle_packet (Packet pkt) { + // debug("handle packet of type: %s", pkt.pkt_type); + if (pkt.pkt_type == Packet.ENCRYPTED) { + warning ("received packet with eplicit encryption, this usually indicates a protocol version < 6 type packet, such pacckets are no longer supported, dropping.."); + } else { + // signal that we got a packet + this.packet_received (pkt); + } + } } \ No newline at end of file diff --git a/src/mconnect/devicemanager-proxy.vala b/src/mconnect/devicemanager-proxy.vala index 2db0e3f..5d0b056 100644 --- a/src/mconnect/devicemanager-proxy.vala +++ b/src/mconnect/devicemanager-proxy.vala @@ -20,156 +20,158 @@ using Gee; [DBus (name = "org.mconnect.DeviceManager")] -class DeviceManagerDBusProxy : Object -{ - private DeviceManager manager; - - public string certificate { - owned get { return Core.instance().certificate.certificate_pem; } - private set {} - } - - public signal void device_added(string path); - - public signal void device_removed(string path); - - private const string DBUS_PATH = "/org/mconnect/manager"; - private DBusConnection bus = null; - private HashMap devices; - - private int device_idx = 0; - - public DeviceManagerDBusProxy.with_manager(DBusConnection bus, - DeviceManager manager) { - this.manager = manager; - this.bus = bus; - this.devices = new HashMap(); - - manager.found_new_device.connect((d) => { - this.add_device(d); - }); - manager.device_capability_added.connect(this.add_device_capability); - } - - [DBus (visible = false)] - public void publish() throws IOError { - assert(this.bus != null); - - this.bus.register_object(DBUS_PATH, this); - } - - /** - * allow_device: - * @path: device object path - * - * Allow given device - */ - public void allow_device(string path) { - debug("allow device %s", path); - - var dev_proxy = this.devices.@get(path); - - if (dev_proxy == null) { - warning("no device under path %s", path); - return; - } - - this.manager.allow_device(dev_proxy.device); - } - - /** - * disallow_device: - * @path: device object path - * - * Disallow given device - */ - public void disallow_device(string path) { - debug("disallow device %s", path); - - var dev_proxy = this.devices.@get(path); - - if (dev_proxy == null) { - warning("no device under path %s", path); - return; - } - - this.manager.disallow_device(dev_proxy.device); - } - - /** - * list_devices: - * - * Returns a list of DBus paths of all known devices - */ - public ObjectPath[] list_devices() { - ObjectPath[] devices = {}; - - foreach (var path in this.devices.keys) { - devices += new ObjectPath(path); - } - return devices; - } - - private void add_device(Device dev) { - var path = make_device_path(); - var device_proxy = new DeviceDBusProxy.for_device_with_path(dev, - new ObjectPath(path)); - - this.devices.@set(path, device_proxy); - - info("register device %s under path %s", - dev.to_string(), path); - device_proxy.bus_register(this.bus); - device_added(path); - } - - private DeviceDBusProxy? find_proxy_for_device(Device dev) { - DeviceDBusProxy dp = null; - foreach (var entry in this.devices.entries) { - if (entry.value.device == dev) { - dp = entry.value; - break; - } - } - return dp; - } - - private void add_device_capability(Device dev, - string capability, - PacketHandlerInterface iface) { - DeviceDBusProxy dp = find_proxy_for_device(dev); - - if (dp == null) { - warning("no bus proxy for device %s", dev.to_string()); - return; - } - - if (dp.has_handler(capability)) { - return; - } - - info("add capability handler %s for device at path %s", - capability, dp.object_path.to_string()); - - var h = PacketHandlersProxy.new_device_capability_handler(dev, - capability, - iface); - if (h != null) { - h.bus_register(this.bus, dp.object_path); - } - } - - /** - * make_device_path: - * - * return device path string that can be used as ObjectPath - */ - private string make_device_path() { - var path = "/org/mconnect/device/%d".printf(this.device_idx); - - // bump device index - this.device_idx++; - - return path; - } -} +class DeviceManagerDBusProxy : Object { + private DeviceManager manager; + + public string certificate { + owned get { + return Core.instance ().certificate.certificate_pem; + } + private set { + } + } + + public signal void device_added (string path); + + public signal void device_removed (string path); + + private const string DBUS_PATH = "/org/mconnect/manager"; + private DBusConnection bus = null; + private HashMap devices; + + private int device_idx = 0; + + public DeviceManagerDBusProxy.with_manager (DBusConnection bus, + DeviceManager manager) { + this.manager = manager; + this.bus = bus; + this.devices = new HashMap(); + + manager.found_new_device.connect ((d) => { + this.add_device (d); + }); + manager.device_capability_added.connect (this.add_device_capability); + } + + [DBus (visible = false)] + public void publish () throws IOError { + assert (this.bus != null); + + this.bus.register_object (DBUS_PATH, this); + } + + /** + * allow_device: + * @path: device object path + * + * Allow given device + */ + public void allow_device (string path) { + debug ("allow device %s", path); + + var dev_proxy = this.devices.@get (path); + + if (dev_proxy == null) { + warning ("no device under path %s", path); + return; + } + + this.manager.allow_device (dev_proxy.device); + } + + /** + * disallow_device: + * @path: device object path + * + * Disallow given device + */ + public void disallow_device (string path) { + debug ("disallow device %s", path); + + var dev_proxy = this.devices.@get (path); + + if (dev_proxy == null) { + warning ("no device under path %s", path); + return; + } + + this.manager.disallow_device (dev_proxy.device); + } + + /** + * list_devices: + * + * Returns a list of DBus paths of all known devices + */ + public ObjectPath[] list_devices () { + ObjectPath[] devices = {}; + + foreach (var path in this.devices.keys) { + devices += new ObjectPath (path); + } + return devices; + } + + private void add_device (Device dev) { + var path = make_device_path (); + var device_proxy = new DeviceDBusProxy.for_device_with_path (dev, + new ObjectPath (path)); + + this.devices.@set (path, device_proxy); + + info ("register device %s under path %s", + dev.to_string (), path); + device_proxy.bus_register (this.bus); + device_added (path); + } + + private DeviceDBusProxy ? find_proxy_for_device (Device dev) { + DeviceDBusProxy dp = null; + foreach (var entry in this.devices.entries) { + if (entry.value.device == dev) { + dp = entry.value; + break; + } + } + return dp; + } + + private void add_device_capability (Device dev, + string capability, + PacketHandlerInterface iface) { + DeviceDBusProxy dp = find_proxy_for_device (dev); + + if (dp == null) { + warning ("no bus proxy for device %s", dev.to_string ()); + return; + } + + if (dp.has_handler (capability)) { + return; + } + + info ("add capability handler %s for device at path %s", + capability, dp.object_path.to_string ()); + + var h = PacketHandlersProxy.new_device_capability_handler (dev, + capability, + iface); + if (h != null) { + h.bus_register (this.bus, dp.object_path); + } + } + + /** + * make_device_path: + * + * return device path string that can be used as ObjectPath + */ + private string make_device_path () { + var path = "/org/mconnect/device/%d".printf (this.device_idx); + + // bump device index + this.device_idx++; + + return path; + } +} \ No newline at end of file diff --git a/src/mconnect/devicemanager.vala b/src/mconnect/devicemanager.vala index 4463f37..6436261 100644 --- a/src/mconnect/devicemanager.vala +++ b/src/mconnect/devicemanager.vala @@ -19,250 +19,245 @@ */ using Gee; -class DeviceManager : GLib.Object -{ - public signal void found_new_device(Device dev); - public signal void device_capability_added(Device dev, - string capability, - PacketHandlerInterface handler); - - public const string DEVICES_CACHE_FILE = "devices"; - - private HashMap devices; - - public DeviceManager() { - debug("device manager.."); - - this.devices = new HashMap(); - } - - /** - * Obtain path to devices cache file - */ - private string get_cache_file() { - var cache_file = Path.build_filename(Core.get_cache_dir(), - DEVICES_CACHE_FILE); - vdebug("cache file: %s", cache_file); - - // make sure that cache dir exists - DirUtils.create_with_parents(Core.get_cache_dir(), - 0700); - - return cache_file; - } - - /** - * Load known devices from cache and attempt pairing. - */ - public void load_cache() { - var cache_file = get_cache_file(); - - debug("try loading devices from device cache %s", cache_file); - - var kf = new KeyFile(); - try { - kf.load_from_file(cache_file, KeyFileFlags.NONE); - - string[] groups = kf.get_groups(); - - foreach (string group in groups) { - var dev = Device.new_from_cache(kf, group); - if (dev != null) { - debug("device %s from cache", dev.to_string()); - handle_new_device(dev); - } - } - } catch (Error e) { - debug("error loading cache file: %s", e.message); - } - } - - /** - * Update contents of device cache - */ - private void update_cache() { - // debug("update devices cache"); - - if (devices.size == 0) - return; - - var kf = new KeyFile(); - - foreach (var dev in devices.values) { - dev.to_cache(kf, dev.device_name); - } - - try { - // debug("saving to cache"); - FileUtils.set_contents(get_cache_file(), - kf.to_data()); - } catch (FileError e) { - warning("failed to save to cache file %s: %s", - get_cache_file(), e.message); - } - } - - public void handle_discovered_device(DiscoveredDevice discovered_dev) { - debug("found device: %s", discovered_dev.to_string()); - - var new_dev = new Device.from_discovered_device(discovered_dev); - - handle_new_device(new_dev); - } - - public void handle_new_device(Device new_dev) { - var is_new = false; - string unique = new_dev.to_unique_string(); - vdebug("device key: %s", unique); - - if (this.devices.has_key(unique) == false) { - debug("adding new device with key: %s", unique); - - this.devices.@set(unique, new_dev); - - is_new = true; - - } else { - debug("device %s already present", unique); - } - - var dev = this.devices.@get(unique); - - // notify everyone that a new device appeared - if (is_new) { - // make sure that this happens before we update device data so that - // all subscribeds of found_new_device() signal have a chance to - // setup eveything they need - found_new_device(dev); - } - - if (is_new) { - dev.capability_added.connect(this.device_capability_added_cb); - dev.capability_removed.connect(this.device_capability_removed_cb); - } - // update device information - dev.update_from_device(new_dev); - - debug("allowed? %s", dev.allowed.to_string()); - // check if device is whitelisted in configuration - if (!dev.allowed && device_allowed_in_config(dev)) { - dev.allowed = true; - } - - // update devices cache - update_cache(); - - if (dev.allowed) { - // device is allowed - activate_device(dev); - } else { - warning("skipping device %s activation, device not allowed", - dev.to_string()); - } - - } - - private void activate_device(Device dev) { - info("activating device %s, active: %s", dev.to_string(), - dev.is_active.to_string()); - - if (!dev.is_active) { - dev.paired.connect(this.device_paired); - dev.disconnected.connect(this.device_disconnected); - - dev.activate(); - } - } - - /** - * device_allowed_in_config: - * @dev device - * - * Returns true if a matching device is enabled via configuration file. - */ - private bool device_allowed_in_config(Device dev) { - if (dev.allowed) - return true; - - var core = Core.instance(); - - var in_config = core.config.is_device_allowed(dev.device_name, - dev.device_type); - return in_config; - } - - private void device_paired(Device dev, bool status) { - info("device %s pair status change: %s", - dev.to_string(), status.to_string()); - - update_cache(); - - if (status == false) { - // we're no longer interested in paired singnal - dev.paired.disconnect(this.device_paired); - - // we're not paired anymore, deactivate if needed - dev.deactivate(); - } - - } - - private void device_capability_added_cb(Device dev, string cap) { - info("capability %s added to device %s", cap, dev.to_string()); - - if (dev.has_capability_handler(cap)) { - return; - } - - var core = Core.instance(); - var h = core.handlers.get_capability_handler(cap); - if (h != null) { - dev.register_capability_handler(cap, h); - - device_capability_added(dev, cap, h); - - } else { - warning("no handler for capability %s", cap); - } - } - - private void device_capability_removed_cb(Device dev, string cap) { - info("capability %s removed from device %s", cap, dev.to_string()); - } - - private void device_disconnected(Device dev) { - debug("device %s got disconnected", dev.to_string()); - - dev.paired.disconnect(this.device_paired); - dev.disconnected.disconnect(this.device_disconnected); - } - - /** - * allow_device: - * @path: device object path - * - * Allow given device - */ - public void allow_device(Device dev) { - dev.allowed = true; - - // update device cache - update_cache(); - - // maybe activate if needed - activate_device(dev); - } - - /** - * disallow_device: - * @path: device object path - * - * Disallow given device - */ - public void disallow_device(Device dev) { - dev.allowed = false; - - // update device cache - update_cache(); - } -} +class DeviceManager : GLib.Object { + public signal void found_new_device (Device dev); + public signal void device_capability_added (Device dev, + string capability, + PacketHandlerInterface handler); + + public const string DEVICES_CACHE_FILE = "devices"; + + private HashMap devices; + + public DeviceManager () { + debug ("device manager.."); + + this.devices = new HashMap(); + } + + /** + * Obtain path to devices cache file + */ + private string get_cache_file () { + var cache_file = Path.build_filename (Core.get_cache_dir (), + DEVICES_CACHE_FILE); + vdebug ("cache file: %s", cache_file); + + // make sure that cache dir exists + DirUtils.create_with_parents (Core.get_cache_dir (), + 0700); + + return cache_file; + } + + /** + * Load known devices from cache and attempt pairing. + */ + public void load_cache () { + var cache_file = get_cache_file (); + + debug ("try loading devices from device cache %s", cache_file); + + var kf = new KeyFile (); + try { + kf.load_from_file (cache_file, KeyFileFlags.NONE); + + string[] groups = kf.get_groups (); + + foreach (string group in groups) { + var dev = Device.new_from_cache (kf, group); + if (dev != null) { + debug ("device %s from cache", dev.to_string ()); + handle_new_device (dev); + } + } + } catch (Error e) { + debug ("error loading cache file: %s", e.message); + } + } + + /** + * Update contents of device cache + */ + private void update_cache () { + // debug("update devices cache"); + + if (devices.size == 0) + return; + + var kf = new KeyFile (); + + foreach (var dev in devices.values) { + dev.to_cache (kf, dev.device_name); + } + + try { + // debug("saving to cache"); + FileUtils.set_contents (get_cache_file (), + kf.to_data ()); + } catch (FileError e) { + warning ("failed to save to cache file %s: %s", + get_cache_file (), e.message); + } + } + + public void handle_discovered_device (DiscoveredDevice discovered_dev) { + debug ("found device: %s", discovered_dev.to_string ()); + + var new_dev = new Device.from_discovered_device (discovered_dev); + + handle_new_device (new_dev); + } + + public void handle_new_device (Device new_dev) { + var is_new = false; + string unique = new_dev.to_unique_string (); + vdebug ("device key: %s", unique); + + if (this.devices.has_key (unique) == false) { + debug ("adding new device with key: %s", unique); + + this.devices.@set (unique, new_dev); + + is_new = true; + } else { + debug ("device %s already present", unique); + } + + var dev = this.devices.@get (unique); + + // notify everyone that a new device appeared + if (is_new) { + // make sure that this happens before we update device data so that + // all subscribeds of found_new_device() signal have a chance to + // setup eveything they need + found_new_device (dev); + } + + if (is_new) { + dev.capability_added.connect (this.device_capability_added_cb); + dev.capability_removed.connect (this.device_capability_removed_cb); + } + // update device information + dev.update_from_device (new_dev); + + debug ("allowed? %s", dev.allowed.to_string ()); + // check if device is whitelisted in configuration + if (!dev.allowed && device_allowed_in_config (dev)) { + dev.allowed = true; + } + + // update devices cache + update_cache (); + + if (dev.allowed) { + // device is allowed + activate_device (dev); + } else { + warning ("skipping device %s activation, device not allowed", + dev.to_string ()); + } + } + + private void activate_device (Device dev) { + info ("activating device %s, active: %s", dev.to_string (), + dev.is_active.to_string ()); + + if (!dev.is_active) { + dev.paired.connect (this.device_paired); + dev.disconnected.connect (this.device_disconnected); + + dev.activate (); + } + } + + /** + * device_allowed_in_config: + * @dev device + * + * Returns true if a matching device is enabled via configuration file. + */ + private bool device_allowed_in_config (Device dev) { + if (dev.allowed) + return true; + + var core = Core.instance (); + + var in_config = core.config.is_device_allowed (dev.device_name, + dev.device_type); + return in_config; + } + + private void device_paired (Device dev, bool status) { + info ("device %s pair status change: %s", + dev.to_string (), status.to_string ()); + + update_cache (); + + if (status == false) { + // we're no longer interested in paired singnal + dev.paired.disconnect (this.device_paired); + + // we're not paired anymore, deactivate if needed + dev.deactivate (); + } + } + + private void device_capability_added_cb (Device dev, string cap) { + info ("capability %s added to device %s", cap, dev.to_string ()); + + if (dev.has_capability_handler (cap)) { + return; + } + + var core = Core.instance (); + var h = core.handlers.get_capability_handler (cap); + if (h != null) { + dev.register_capability_handler (cap, h); + + device_capability_added (dev, cap, h); + } else { + warning ("no handler for capability %s", cap); + } + } + + private void device_capability_removed_cb (Device dev, string cap) { + info ("capability %s removed from device %s", cap, dev.to_string ()); + } + + private void device_disconnected (Device dev) { + debug ("device %s got disconnected", dev.to_string ()); + + dev.paired.disconnect (this.device_paired); + dev.disconnected.disconnect (this.device_disconnected); + } + + /** + * allow_device: + * @path: device object path + * + * Allow given device + */ + public void allow_device (Device dev) { + dev.allowed = true; + + // update device cache + update_cache (); + + // maybe activate if needed + activate_device (dev); + } + + /** + * disallow_device: + * @path: device object path + * + * Disallow given device + */ + public void disallow_device (Device dev) { + dev.allowed = false; + + // update device cache + update_cache (); + } +} \ No newline at end of file diff --git a/src/mconnect/discovereddevice.vala b/src/mconnect/discovereddevice.vala index 15a7dfd..e795f97 100644 --- a/src/mconnect/discovereddevice.vala +++ b/src/mconnect/discovereddevice.vala @@ -23,60 +23,75 @@ */ class DiscoveredDevice : Object { - public string device_id { get; private set; default = ""; } - public string device_name { get; private set; default = ""; } - public string device_type { get; private set; default = ""; } - public uint protocol_version {get; private set; default = 5; } - public uint tcp_port {get; private set; default = 1714; } - public InetAddress host { get; private set; default = null; } - public string[] outgoing_capabilities { get; private set; default = null; } - public string[] incoming_capabilities { get; private set; default = null; } + public string device_id { + get; private set; default = ""; + } + public string device_name { + get; private set; default = ""; + } + public string device_type { + get; private set; default = ""; + } + public uint protocol_version { + get; private set; default = 5; + } + public uint tcp_port { + get; private set; default = 1714; + } + public InetAddress host { + get; private set; default = null; + } + public string[] outgoing_capabilities { + get; private set; default = null; + } + public string[] incoming_capabilities { + get; private set; default = null; + } - /** - * Constructs DiscoveredDevice based on identity packet. - * - * @param pkt identity packet - * @param host source host that the packet came from - */ - public DiscoveredDevice.from_identity(Packet pkt, InetAddress host) { + /** + * Constructs DiscoveredDevice based on identity packet. + * + * @param pkt identity packet + * @param host source host that the packet came from + */ + public DiscoveredDevice.from_identity (Packet pkt, InetAddress host) { - debug("got packet: %s", pkt.to_string()); + debug ("got packet: %s", pkt.to_string ()); - var body = pkt.body; - this.host = host; - this.device_name = body.get_string_member("deviceName"); - this.device_id = body.get_string_member("deviceId"); - this.device_type = body.get_string_member("deviceType"); - this.protocol_version = (int) body.get_int_member("protocolVersion"); - this.tcp_port = (uint) body.get_int_member("tcpPort"); + var body = pkt.body; + this.host = host; + this.device_name = body.get_string_member ("deviceName"); + this.device_id = body.get_string_member ("deviceId"); + this.device_type = body.get_string_member ("deviceType"); + this.protocol_version = (int) body.get_int_member ("protocolVersion"); + this.tcp_port = (uint) body.get_int_member ("tcpPort"); - var incoming = body.get_array_member("incomingCapabilities"); - var outgoing = body.get_array_member("outgoingCapabilities"); - this.outgoing_capabilities = new string[outgoing.get_length()]; - this.incoming_capabilities = new string[incoming.get_length()]; + var incoming = body.get_array_member ("incomingCapabilities"); + var outgoing = body.get_array_member ("outgoingCapabilities"); + this.outgoing_capabilities = new string[outgoing.get_length ()]; + this.incoming_capabilities = new string[incoming.get_length ()]; - incoming.foreach_element((a, i, n) => { - this.incoming_capabilities[i] = n.get_string(); - }); - outgoing.foreach_element((a, i, n) => { - this.outgoing_capabilities[i] = n.get_string(); - }); + incoming.foreach_element ((a, i, n) => { + this.incoming_capabilities[i] = n.get_string (); + }); + outgoing.foreach_element ((a, i, n) => { + this.outgoing_capabilities[i] = n.get_string (); + }); - debug("discovered new device: %s", this.to_string()); - } + debug ("discovered new device: %s", this.to_string ()); + } - public string to_string() { - return "discovered-%s-%s-%s-%u".printf(this.device_id, - this.device_name, - this.device_type, - this.protocol_version); - } - - public string to_unique_string() { - return Utils.make_unique_device_string(this.device_id, - this.device_name, - this.device_type, - this.protocol_version); - } + public string to_string () { + return "discovered-%s-%s-%s-%u".printf (this.device_id, + this.device_name, + this.device_type, + this.protocol_version); + } + public string to_unique_string () { + return Utils.make_unique_device_string (this.device_id, + this.device_name, + this.device_type, + this.protocol_version); + } } \ No newline at end of file diff --git a/src/mconnect/discovery.vala b/src/mconnect/discovery.vala index 1d3f50b..d965aa7 100644 --- a/src/mconnect/discovery.vala +++ b/src/mconnect/discovery.vala @@ -18,83 +18,81 @@ * Maciek Borzecki */ -class Discovery : GLib.Object -{ - private Socket socket = null; +class Discovery : GLib.Object { + private Socket socket = null; - public signal void device_found(DiscoveredDevice dev); + public signal void device_found (DiscoveredDevice dev); - public Discovery() { - } + public Discovery () { + } - ~Discovery() { - debug("cleaning up discovery..."); - if (this.socket != null) { - this.socket.close(); - } - } + ~Discovery () { + debug ("cleaning up discovery..."); + if (this.socket != null) { + this.socket.close (); + } + } - public void listen() throws Error { - this.socket = new Socket(SocketFamily.IPV4, - SocketType.DATAGRAM, - SocketProtocol.UDP); - var sa = new InetSocketAddress(new InetAddress.any(SocketFamily.IPV4), - 1714); - debug("start listening for new devices at: %s:%u", - sa.address.to_string(), sa.port); + public void listen () throws Error { + this.socket = new Socket (SocketFamily.IPV4, + SocketType.DATAGRAM, + SocketProtocol.UDP); + var sa = new InetSocketAddress (new InetAddress.any (SocketFamily.IPV4), + 1714); + debug ("start listening for new devices at: %s:%u", + sa.address.to_string (), sa.port); - try { - socket.bind(sa, false); - } catch (Error e) { - this.socket.close(); - this.socket = null; - throw e; - } + try { + socket.bind (sa, false); + } catch (Error e) { + this.socket.close (); + this.socket = null; + throw e; + } - var source = socket.create_source(IOCondition.IN); - source.set_callback((s, c) => { - this.incomingPacket(); - return true; - }); - source.attach(MainContext.default()); - } + var source = socket.create_source (IOCondition.IN); + source.set_callback ((s, c) => { + this.incomingPacket (); + return true; + }); + source.attach (MainContext.default ()); + } - private void incomingPacket() { - vdebug("incoming packet"); + private void incomingPacket () { + vdebug ("incoming packet"); - uint8 buffer[4096]; - SocketAddress sa; - InetSocketAddress isa; + uint8 buffer[4096]; + SocketAddress sa; + InetSocketAddress isa; - try { - ssize_t read = this.socket.receive_from(out sa, buffer); - isa = (InetSocketAddress)sa; - vdebug("got %zd bytes from: %s:%u", read, - isa.address.to_string(), isa.port); - } catch (Error e) { - warning("failed to receive packet: %s", e.message); - return; - } + try { + ssize_t read = this.socket.receive_from (out sa, buffer); + isa = (InetSocketAddress) sa; + vdebug ("got %zd bytes from: %s:%u", read, + isa.address.to_string (), isa.port); + } catch (Error e) { + warning ("failed to receive packet: %s", e.message); + return; + } - vdebug("message data: %s", (string)buffer); + vdebug ("message data: %s", (string) buffer); - this.parsePacketFromHost((string) buffer, isa.address); - } + this.parsePacketFromHost ((string) buffer, isa.address); + } - private void parsePacketFromHost(string data, InetAddress host) - { - // expecing an identity packet - var pkt = Packet.new_from_data(data); - if (pkt.pkt_type != Packet.IDENTITY) { - message("unexpected packet type %s from device %s", - pkt.pkt_type, host.to_string()); - return; - } + private void parsePacketFromHost (string data, InetAddress host) { + // expecing an identity packet + var pkt = Packet.new_from_data (data); + if (pkt.pkt_type != Packet.IDENTITY) { + message ("unexpected packet type %s from device %s", + pkt.pkt_type, host.to_string ()); + return; + } - var dev = new DiscoveredDevice.from_identity(pkt, host); - message("connection from device: \'%s\', responds at: %s:%u", - dev.device_name, host.to_string(), dev.tcp_port); + var dev = new DiscoveredDevice.from_identity (pkt, host); + message ("connection from device: \'%s\', responds at: %s:%u", + dev.device_name, host.to_string (), dev.tcp_port); - device_found(dev); - } -} + device_found (dev); + } +} \ No newline at end of file diff --git a/src/mconnect/io-job.vala b/src/mconnect/io-job.vala index 7b442fe..ed5dcdf 100644 --- a/src/mconnect/io-job.vala +++ b/src/mconnect/io-job.vala @@ -19,55 +19,57 @@ using Logging; class IOCopyJob : Object { - private InputStream from = null; - private OutputStream to = null; + private InputStream from = null; + private OutputStream to = null; - public IOCopyJob(InputStream from, OutputStream to) { - this.from = from; - this.to = to; - } + public IOCopyJob (InputStream from, OutputStream to) { + this.from = from; + this.to = to; + } - /** - * transfer_async: - * @cancel: cancellable - * - * Starty asynchronous transfer of data from @from stream to @to stream. - * - * @return number of bytes transferred if no error occurred - */ - public async uint64 start_async(Cancellable? cancel) throws Error { - uint64 bytes_done = 0; - var chunk_size = 4096; - var max_chunk_size = 64 * 1024; - while (true) { - var data = yield this.from.read_bytes_async(chunk_size, - Priority.DEFAULT, - cancel); - vdebug("read %d bytes", data.length); - if (data.length == 0) { - break; - } - yield this.to.write_bytes_async(data, Priority.DEFAULT, - cancel); - bytes_done += data.length; - this.progress(bytes_done); + /** + * transfer_async: + * @cancel: cancellable + * + * Starty asynchronous transfer of data from @from stream to @to stream. + * + * @return number of bytes transferred if no error occurred + */ + public async uint64 start_async (Cancellable ? cancel) throws Error { + uint64 bytes_done = 0; + var chunk_size = 4096; + var max_chunk_size = 64 * 1024; + while (true) { + var data = yield this.from.read_bytes_async (chunk_size, + Priority.DEFAULT, + cancel); - if (data.length == chunk_size) - chunk_size = 2 * chunk_size; + vdebug ("read %d bytes", data.length); + if (data.length == 0) { + break; + } + yield this.to.write_bytes_async (data, Priority.DEFAULT, + cancel); - if (chunk_size > max_chunk_size) - chunk_size = max_chunk_size; - } + bytes_done += data.length; + this.progress (bytes_done); - debug("transfer done, got %s bytes", format_size(bytes_done)); - return bytes_done; - } + if (data.length == chunk_size) + chunk_size = 2 * chunk_size; - /** - * progress: - * @bytes_down: number of bytes transferred - * - * Indicate transfer progress - */ - public signal void progress(uint64 bytes_done); + if (chunk_size > max_chunk_size) + chunk_size = max_chunk_size; + } + + debug ("transfer done, got %s bytes", format_size (bytes_done)); + return bytes_done; + } + + /** + * progress: + * @bytes_down: number of bytes transferred + * + * Indicate transfer progress + */ + public signal void progress (uint64 bytes_done); } \ No newline at end of file diff --git a/src/mconnect/logging.vala b/src/mconnect/logging.vala index cdd9791..26988da 100644 --- a/src/mconnect/logging.vala +++ b/src/mconnect/logging.vala @@ -17,18 +17,17 @@ */ namespace Logging { - - public bool VERBOSE = false; + + public bool VERBOSE = false; /** * enable_vdebug: * * Enable verbose debug logging */ -void enable_vdebug() { - VERBOSE = true; -} - + void enable_vdebug () { + VERBOSE = true; + } } /** @@ -37,10 +36,9 @@ void enable_vdebug() { * * Same as debug() but looks at verbose debug flag */ -void vdebug(string format, ...) { - if (Logging.VERBOSE == true) { - var l = va_list(); - logv(null, LogLevelFlags.LEVEL_DEBUG, format, l); - } -} - +void vdebug (string format, ...) { + if (Logging.VERBOSE == true) { + var l = va_list (); + logv (null, LogLevelFlags.LEVEL_DEBUG, format, l); + } +} \ No newline at end of file diff --git a/src/mconnect/main.vala b/src/mconnect/main.vala index 50d2a22..6a24fd6 100644 --- a/src/mconnect/main.vala +++ b/src/mconnect/main.vala @@ -17,15 +17,14 @@ * AUTHORS * Maciek Borzecki */ -public static int main(string[] args) -{ - var app = new Mconn.Application(); +public static int main (string[] args) { + var app = new Mconn.Application (); - // needed for mousepad protocol handler - Gdk.init(ref args); + // needed for mousepad protocol handler + Gdk.init (ref args); - // needed for clipboard sharing - Gtk.init(ref args); + // needed for clipboard sharing + Gtk.init (ref args); - return app.run(args); + return app.run (args); } \ No newline at end of file diff --git a/src/mconnect/mousepad.vala b/src/mconnect/mousepad.vala index 63cb801..86e4fa6 100644 --- a/src/mconnect/mousepad.vala +++ b/src/mconnect/mousepad.vala @@ -20,138 +20,136 @@ class MousepadHandler : Object, PacketHandlerInterface { - public const string MOUSEPAD = "kdeconnect.mousepad.request"; - public const string MOUSEPAD_PACKET = "kdeconnect.mousepad"; - - private Gdk.Display _display; - - public string get_pkt_type() { - return MOUSEPAD; - } - - private MousepadHandler() { - - } - - public static MousepadHandler instance() { - var ms = new MousepadHandler(); - - if (Atspi.init() > 1) { - warning("failed to initialize AT-SPI"); - } - ms._display = Gdk.Display.get_default(); - if (ms._display == null) { - warning("failed to obtain display"); - } - return ms; - } - - public void use_device(Device dev) { - debug("use device %s for mouse/keyboard input", dev.to_string()); - dev.message.connect(this.message); - } - - public void release_device(Device dev) { - debug("release device %s ", dev.to_string()); - dev.message.disconnect(this.message); - } - - private void message(Device dev, Packet pkt) { - if (pkt.pkt_type != MOUSEPAD_PACKET && pkt.pkt_type != MOUSEPAD) { - return; - } - - debug("got mousepad packet"); - - if (_display == null) { - warning("display not initialized"); - return; - } - if (pkt.body.has_member("singleclick")) { - // single click - debug("single click"); - send_click(1); - } else if (pkt.body.has_member("doubleclick")) { - send_click(1, true); - } else if (pkt.body.has_member("rightclick")) { - send_click(3); - } else if (pkt.body.has_member("middleclick")) { - send_click(2); - } else if (pkt.body.has_member("dx") && pkt.body.has_member("dy")) { - // motion/position - double dx = pkt.body.get_double_member("dx"); - double dy = pkt.body.get_double_member("dy"); - debug("position: %f x %f", dx, dy); - - move_cursor_relative(dx, dy); - - } else if (pkt.body.has_member("key")) { - string key = pkt.body.get_string_member("key"); - debug("got key: %s", key); - send_key(key); - } else if (pkt.body.has_member("specialKey")) { - var keynum = pkt.body.get_int_member("specialKey"); - debug("got special key: %s", keynum.to_string()); - send_keysym((uint) keynum); - } - } - - private void move_cursor_relative(double dx, double dy) { - try { - Atspi.generate_mouse_event((long)dx, (long)dy, "rel"); - } catch (Error e) { - warning("failed to generate mouse move event: %s", e.message); - } - } - - private void send_click(int button, bool doubleclick = false) { - var etype = "b1c"; - if (button == 2) { - etype = "b2c"; - } else if (button == 3) { - etype = "b3c"; - } - try { - int x, y; - _display.get_pointer(null, out x, out y, null); - Atspi.generate_mouse_event(x, y, etype); - if (doubleclick) { - Atspi.generate_mouse_event(x, y, etype); - } - } catch (Error e) { - warning("failed to generate mouse click event: %s", e.message); - } - } - - private void send_key(string key) { - try { - Atspi.generate_keyboard_event(0, key, - Atspi.KeySynthType.STRING); - } catch (Error e) { - warning("failed to generate keyboard event: %s", e.message); - } - } - - private void send_keysym(uint key) { - uint keyval = 0; - if (key == 12) { - keyval = Gdk.keyval_from_name("Return"); - } else if (key == 1) { - keyval = Gdk.keyval_from_name("BackSpace"); - } - - if (keyval == 0) { - warning("could not identify key %u", key); - return; - } - - debug("keyval %x %s", keyval, Gdk.keyval_name(keyval)); - try { - Atspi.generate_keyboard_event(keyval, null, - Atspi.KeySynthType.PRESSRELEASE - | Atspi.KeySynthType.SYM); - } catch (Error e) { - warning("failed to generate keyboard event: %s", e.message); - } - } + public const string MOUSEPAD = "kdeconnect.mousepad.request"; + public const string MOUSEPAD_PACKET = "kdeconnect.mousepad"; + + private Gdk.Display _display; + + public string get_pkt_type () { + return MOUSEPAD; + } + + private MousepadHandler () { + } + + public static MousepadHandler instance () { + var ms = new MousepadHandler (); + + if (Atspi.init () > 1) { + warning ("failed to initialize AT-SPI"); + } + ms._display = Gdk.Display.get_default (); + if (ms._display == null) { + warning ("failed to obtain display"); + } + return ms; + } + + public void use_device (Device dev) { + debug ("use device %s for mouse/keyboard input", dev.to_string ()); + dev.message.connect (this.message); + } + + public void release_device (Device dev) { + debug ("release device %s ", dev.to_string ()); + dev.message.disconnect (this.message); + } + + private void message (Device dev, Packet pkt) { + if (pkt.pkt_type != MOUSEPAD_PACKET && pkt.pkt_type != MOUSEPAD) { + return; + } + + debug ("got mousepad packet"); + + if (_display == null) { + warning ("display not initialized"); + return; + } + if (pkt.body.has_member ("singleclick")) { + // single click + debug ("single click"); + send_click (1); + } else if (pkt.body.has_member ("doubleclick")) { + send_click (1, true); + } else if (pkt.body.has_member ("rightclick")) { + send_click (3); + } else if (pkt.body.has_member ("middleclick")) { + send_click (2); + } else if (pkt.body.has_member ("dx") && pkt.body.has_member ("dy")) { + // motion/position + double dx = pkt.body.get_double_member ("dx"); + double dy = pkt.body.get_double_member ("dy"); + debug ("position: %f x %f", dx, dy); + + move_cursor_relative (dx, dy); + } else if (pkt.body.has_member ("key")) { + string key = pkt.body.get_string_member ("key"); + debug ("got key: %s", key); + send_key (key); + } else if (pkt.body.has_member ("specialKey")) { + var keynum = pkt.body.get_int_member ("specialKey"); + debug ("got special key: %s", keynum.to_string ()); + send_keysym ((uint) keynum); + } + } + + private void move_cursor_relative (double dx, double dy) { + try { + Atspi.generate_mouse_event ((long) dx, (long) dy, "rel"); + } catch (Error e) { + warning ("failed to generate mouse move event: %s", e.message); + } + } + + private void send_click (int button, bool doubleclick = false) { + var etype = "b1c"; + if (button == 2) { + etype = "b2c"; + } else if (button == 3) { + etype = "b3c"; + } + try { + int x, y; + _display.get_pointer (null, out x, out y, null); + Atspi.generate_mouse_event (x, y, etype); + if (doubleclick) { + Atspi.generate_mouse_event (x, y, etype); + } + } catch (Error e) { + warning ("failed to generate mouse click event: %s", e.message); + } + } + + private void send_key (string key) { + try { + Atspi.generate_keyboard_event (0, key, + Atspi.KeySynthType.STRING); + } catch (Error e) { + warning ("failed to generate keyboard event: %s", e.message); + } + } + + private void send_keysym (uint key) { + uint keyval = 0; + if (key == 12) { + keyval = Gdk.keyval_from_name ("Return"); + } else if (key == 1) { + keyval = Gdk.keyval_from_name ("BackSpace"); + } + + if (keyval == 0) { + warning ("could not identify key %u", key); + return; + } + + debug ("keyval %x %s", keyval, Gdk.keyval_name (keyval)); + try { + Atspi.generate_keyboard_event (keyval, null, + Atspi.KeySynthType.PRESSRELEASE + | Atspi.KeySynthType.SYM); + } catch (Error e) { + warning ("failed to generate keyboard event: %s", e.message); + } + } } \ No newline at end of file diff --git a/src/mconnect/notification.vala b/src/mconnect/notification.vala index db08f78..76836ce 100644 --- a/src/mconnect/notification.vala +++ b/src/mconnect/notification.vala @@ -1,4 +1,4 @@ - /* ex:ts=4:sw=4:sts=4:et */ +/* ex:ts=4:sw=4:sts=4:et */ /* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify @@ -21,125 +21,120 @@ using Gee; class NotificationHandler : Object, PacketHandlerInterface { - private const string NOTIFICATION = "kdeconnect.notification"; - - private HashMap _pending_notifications; - - public string get_pkt_type() { - return NOTIFICATION; - } - - private NotificationHandler() { - _pending_notifications = new HashMap(); - } - - public static NotificationHandler instance() { - return new NotificationHandler(); - } - - public void use_device(Device dev) { - dev.message.connect(this.message); - } - - public void release_device(Device dev) { - dev.message.disconnect(this.message); - } - - public void message(Device dev, Packet pkt) { - if (pkt.pkt_type != NOTIFICATION) { - return; - } - debug("got notification packet"); - - // get application ID - string id = pkt.body.get_string_member("id"); - - // dialer notifications are handled by telephony plugin - if (id.match_string("com.android.dialer", false) == true) - return; - - // maybe it's a notification about a notification being - // cancelled - if (pkt.body.has_member("isCancel") == true && - pkt.body.get_boolean_member("isCancel") == true) - { - debug("message cancels notification %s", id); - if (_pending_notifications.has_key(id) == true) - { - // cancel out pending notifications - Notify.Notification notif = _pending_notifications.@get(id); - if (notif != null) - { - _pending_notifications.unset(id); - try { - notif.close(); - } catch (Error e) { - critical("error closing notification: %s", e.message); - } - } - } - return; - } - - // check if notification is already known, if so don't show - // anything - if (_pending_notifications.has_key(id) == true) - { - debug("notification %s is known, ignore", id); - return; - } - debug("new notification %s", id); - - // other notifications - if (pkt.body.has_member("appName") == false || - pkt.body.has_member("ticker") == false) - return; - - string app = pkt.body.get_string_member("appName"); - string ticker = pkt.body.get_string_member("ticker"); - - // skip empty notifications - if (ticker.length == 0) - return; - - DateTime time = null; - // check if time was provided, prepend to ticker - if (pkt.body.has_member("time") == true) { - string timestr = pkt.body.get_string_member("time"); - int64 t = int64.parse(timestr); - // time in ms since Epoch, convert to seconds - t /= 1000; - time = new DateTime.from_unix_local(t); - } else { - time = new DateTime.now_local(); - } - // format the body of notification, so that a time information - // is included - if (time != null) - ticker = "%s %s".printf(time.format("%X"), - ticker); - - GLib.message("notification from %s: %s", app, ticker); - - var notif = new Notify.Notification(app, ticker, - "phone"); - try { - // react to closed signal - notif.closed.connect((n) => { - this.handle_closed_notification(id); - }); - notif.show(); - _pending_notifications.@set(id, notif); - } catch (Error e) { - critical("failed to show notification: %s", e.message); - } - } - - private void handle_closed_notification(string id) { - debug("notification %s closed by user", id); - if (_pending_notifications.has_key(id) == true) - { - _pending_notifications.unset(id); - } - } + private const string NOTIFICATION = "kdeconnect.notification"; + + private HashMap _pending_notifications; + + public string get_pkt_type () { + return NOTIFICATION; + } + + private NotificationHandler () { + _pending_notifications = new HashMap(); + } + + public static NotificationHandler instance () { + return new NotificationHandler (); + } + + public void use_device (Device dev) { + dev.message.connect (this.message); + } + + public void release_device (Device dev) { + dev.message.disconnect (this.message); + } + + public void message (Device dev, Packet pkt) { + if (pkt.pkt_type != NOTIFICATION) { + return; + } + debug ("got notification packet"); + + // get application ID + string id = pkt.body.get_string_member ("id"); + + // dialer notifications are handled by telephony plugin + if (id.match_string ("com.android.dialer", false) == true) + return; + + // maybe it's a notification about a notification being + // cancelled + if (pkt.body.has_member ("isCancel") == true && + pkt.body.get_boolean_member ("isCancel") == true) { + debug ("message cancels notification %s", id); + if (_pending_notifications.has_key (id) == true) { + // cancel out pending notifications + Notify.Notification notif = _pending_notifications.@get (id); + if (notif != null) { + _pending_notifications.unset (id); + try { + notif.close (); + } catch (Error e) { + critical ("error closing notification: %s", e.message); + } + } + } + return; + } + + // check if notification is already known, if so don't show + // anything + if (_pending_notifications.has_key (id) == true) { + debug ("notification %s is known, ignore", id); + return; + } + debug ("new notification %s", id); + + // other notifications + if (pkt.body.has_member ("appName") == false || + pkt.body.has_member ("ticker") == false) + return; + + string app = pkt.body.get_string_member ("appName"); + string ticker = pkt.body.get_string_member ("ticker"); + + // skip empty notifications + if (ticker.length == 0) + return; + + DateTime time = null; + // check if time was provided, prepend to ticker + if (pkt.body.has_member ("time") == true) { + string timestr = pkt.body.get_string_member ("time"); + int64 t = int64.parse (timestr); + // time in ms since Epoch, convert to seconds + t /= 1000; + time = new DateTime.from_unix_local (t); + } else { + time = new DateTime.now_local (); + } + // format the body of notification, so that a time information + // is included + if (time != null) + ticker = "%s %s".printf (time.format ("%X"), + ticker); + + GLib.message ("notification from %s: %s", app, ticker); + + var notif = new Notify.Notification (app, ticker, + "phone"); + try { + // react to closed signal + notif.closed.connect ((n) => { + this.handle_closed_notification (id); + }); + notif.show (); + _pending_notifications.@set (id, notif); + } catch (Error e) { + critical ("failed to show notification: %s", e.message); + } + } + + private void handle_closed_notification (string id) { + debug ("notification %s closed by user", id); + if (_pending_notifications.has_key (id) == true) { + _pending_notifications.unset (id); + } + } } \ No newline at end of file diff --git a/src/mconnect/packet.vala b/src/mconnect/packet.vala index da6d873..e5bb43b 100644 --- a/src/mconnect/packet.vala +++ b/src/mconnect/packet.vala @@ -21,155 +21,163 @@ using Json; public errordomain PacketError { - MALFORMED + MALFORMED } class Packet : GLib.Object { - /** - * Payload: - * Wrapper for payload transfer information - */ - public struct Payload { - public uint64 size; - public uint port; - } - - public const int PROTOCOL_VERSION = 7; - - public const string IDENTITY = "kdeconnect.identity"; - public const string PAIR = "kdeconnect.pair"; - public const string ENCRYPTED = "kdeconnect.encrypted"; - - public string pkt_type { get; private set; default = ""; } - public int64 id { get; private set; default = 0; } - public Json.Object body { get; private set; default = null; } - public Payload? payload { get; set; default = null; } - - public Packet(string type, Json.Object body, int64 id = 0) { - this.pkt_type = type; - this.body = body; - if (id == 0) { - this.id = get_real_time() / 1000; - } else { - this.id = id; - } - } - - public static Packet? new_from_data(string data) { - Json.Parser jp = new Json.Parser(); - - try { - jp.load_from_data(data, -1); - // there should be an object at root node - Json.Object root_obj = jp.get_root().get_object(); - if (root_obj == null) - throw new PacketError.MALFORMED("Missing root object"); - - // object needs to have these fields - string[] required_members = {"type", "id", "body"}; - foreach (string m in required_members) { - if (root_obj.has_member(m) == false) - throw new PacketError.MALFORMED(@"Missing $m member"); - } - - string type = root_obj.get_string_member("type"); - int64 id = root_obj.get_int_member("id"); - Json.Object body = root_obj.get_object_member("body"); - - vdebug("packet type: %s", type); - - var pkt = new Packet(type, body, id); - - // ignore payload info for encrypted packets - if (type != ENCRYPTED) { - if (root_obj.has_member("payloadSize") && - root_obj.has_member("payloadTransferInfo")) { - - - var size = root_obj.get_int_member("payloadSize"); - - var pti = root_obj.get_object_member("payloadTransferInfo"); - int64 port = 0; - if (pti == null) { - warning("no payload transfer info?"); - } else { - port = (int) pti.get_int_member("port"); - } - - if (size != 0 && port != 0) { - pkt.payload = {(uint64) size, (uint) port}; - } - } - } - - return pkt; - } catch (Error e) { - message("failed to parse message: \'%s\', error: %s", - data, e.message); - } - return null; - } - - public static Packet new_pair(bool pair = true) { - var builder = new Json.Builder(); - builder.begin_object(); - builder.set_member_name("pair"); - builder.add_boolean_value(pair); - builder.end_object(); - - var data_obj = builder.get_root().get_object(); - - return new Packet(PAIR, data_obj); - } - - public static Packet new_identity(string name, - string device_id, - string[] in_interfaces, - string[] out_interfaces, - string device_type = "desktop") { - var builder = new Json.Builder(); - builder.begin_object(); - builder.set_member_name("deviceName"); - builder.add_string_value(name); - builder.set_member_name("deviceId"); - builder.add_string_value(device_id); - builder.set_member_name("deviceType"); - builder.add_string_value(device_type); - builder.set_member_name("SupportedIncomingInterfaces"); - builder.add_string_value(string.joinv(",", in_interfaces)); - builder.set_member_name("SupportedOutgoingInterfaces"); - builder.add_string_value(string.joinv(",", out_interfaces)); - builder.set_member_name("protocolVersion"); - builder.add_int_value(PROTOCOL_VERSION); - builder.end_object(); - - Json.Object data_obj = builder.get_root().get_object(); - - return new Packet(IDENTITY, data_obj); - } - - public string to_string() { - var gen = new Json.Generator(); - // root node - var root = new Json.Node(Json.NodeType.OBJECT); - var root_obj = new Json.Object(); - root_obj.set_string_member("type", pkt_type); - root_obj.set_int_member("id", id); - root_obj.set_object_member("body", body); - if (this.payload != null) { - root_obj.set_int_member("payloadSize", (int64) this.payload.size); - var pti = new Json.Object(); - pti.set_int_member("port", this.payload.port); - root_obj.set_object_member("payloadTransferInfo", pti); - } - root.set_object(root_obj); - - gen.set_root(root); - gen.set_pretty(false); - - string data = gen.to_data(null); - - return data; - } + /** + * Payload: + * Wrapper for payload transfer information + */ + public struct Payload { + public uint64 size; + public uint port; + } + + public const int PROTOCOL_VERSION = 7; + + public const string IDENTITY = "kdeconnect.identity"; + public const string PAIR = "kdeconnect.pair"; + public const string ENCRYPTED = "kdeconnect.encrypted"; + + public string pkt_type { + get; private set; default = ""; + } + public int64 id { + get; private set; default = 0; + } + public Json.Object body { + get; private set; default = null; + } + public Payload ? payload { + get; set; default = null; + } + + public Packet (string type, Json.Object body, int64 id = 0) { + this.pkt_type = type; + this.body = body; + if (id == 0) { + this.id = get_real_time () / 1000; + } else { + this.id = id; + } + } + + public static Packet ? new_from_data (string data) { + Json.Parser jp = new Json.Parser (); + + try { + jp.load_from_data (data, -1); + // there should be an object at root node + Json.Object root_obj = jp.get_root ().get_object (); + if (root_obj == null) + throw new PacketError.MALFORMED ("Missing root object"); + + // object needs to have these fields + string[] required_members = { "type", "id", "body" }; + foreach (string m in required_members) { + if (root_obj.has_member (m) == false) + throw new PacketError.MALFORMED (@"Missing $m member"); + } + + string type = root_obj.get_string_member ("type"); + int64 id = root_obj.get_int_member ("id"); + Json.Object body = root_obj.get_object_member ("body"); + + vdebug ("packet type: %s", type); + + var pkt = new Packet (type, body, id); + + // ignore payload info for encrypted packets + if (type != ENCRYPTED) { + if (root_obj.has_member ("payloadSize") && + root_obj.has_member ("payloadTransferInfo")) { + + + var size = root_obj.get_int_member ("payloadSize"); + + var pti = root_obj.get_object_member ("payloadTransferInfo"); + int64 port = 0; + if (pti == null) { + warning ("no payload transfer info?"); + } else { + port = (int) pti.get_int_member ("port"); + } + + if (size != 0 && port != 0) { + pkt.payload = { (uint64) size, (uint) port }; + } + } + } + + return pkt; + } catch (Error e) { + message ("failed to parse message: \'%s\', error: %s", + data, e.message); + } + return null; + } + + public static Packet new_pair (bool pair = true) { + var builder = new Json.Builder (); + builder.begin_object (); + builder.set_member_name ("pair"); + builder.add_boolean_value (pair); + builder.end_object (); + + var data_obj = builder.get_root ().get_object (); + + return new Packet (PAIR, data_obj); + } + + public static Packet new_identity (string name, + string device_id, + string[] in_interfaces, + string[] out_interfaces, + string device_type = "desktop") { + var builder = new Json.Builder (); + builder.begin_object (); + builder.set_member_name ("deviceName"); + builder.add_string_value (name); + builder.set_member_name ("deviceId"); + builder.add_string_value (device_id); + builder.set_member_name ("deviceType"); + builder.add_string_value (device_type); + builder.set_member_name ("SupportedIncomingInterfaces"); + builder.add_string_value (string.joinv (",", in_interfaces)); + builder.set_member_name ("SupportedOutgoingInterfaces"); + builder.add_string_value (string.joinv (",", out_interfaces)); + builder.set_member_name ("protocolVersion"); + builder.add_int_value (PROTOCOL_VERSION); + builder.end_object (); + + Json.Object data_obj = builder.get_root ().get_object (); + + return new Packet (IDENTITY, data_obj); + } + + public string to_string () { + var gen = new Json.Generator (); + // root node + var root = new Json.Node (Json.NodeType.OBJECT); + var root_obj = new Json.Object (); + root_obj.set_string_member ("type", pkt_type); + root_obj.set_int_member ("id", id); + root_obj.set_object_member ("body", body); + if (this.payload != null) { + root_obj.set_int_member ("payloadSize", (int64) this.payload.size); + var pti = new Json.Object (); + pti.set_int_member ("port", this.payload.port); + root_obj.set_object_member ("payloadTransferInfo", pti); + } + root.set_object (root_obj); + + gen.set_root (root); + gen.set_pretty (false); + + string data = gen.to_data (null); + + return data; + } } \ No newline at end of file diff --git a/src/mconnect/packethandlerinterface-proxy.vala b/src/mconnect/packethandlerinterface-proxy.vala index 1a19f29..b532209 100644 --- a/src/mconnect/packethandlerinterface-proxy.vala +++ b/src/mconnect/packethandlerinterface-proxy.vala @@ -22,6 +22,6 @@ * PacketHandlerInterfaceProxy: interface of DBus exported packet handler */ interface PacketHandlerInterfaceProxy : Object { - public abstract void bus_register(DBusConnection conn, string path) throws IOError; - public abstract void bus_unregister(DBusConnection conn) throws IOError; + public abstract void bus_register (DBusConnection conn, string path) throws IOError; + public abstract void bus_unregister (DBusConnection conn) throws IOError; } \ No newline at end of file diff --git a/src/mconnect/packethandlerinterface.vala b/src/mconnect/packethandlerinterface.vala index e814e50..98dbdfe 100644 --- a/src/mconnect/packethandlerinterface.vala +++ b/src/mconnect/packethandlerinterface.vala @@ -20,10 +20,9 @@ interface PacketHandlerInterface : Object { - public abstract string get_pkt_type(); + public abstract string get_pkt_type (); - public abstract void use_device(Device dev); - - public abstract void release_device(Device dev); + public abstract void use_device (Device dev); + public abstract void release_device (Device dev); } \ No newline at end of file diff --git a/src/mconnect/packethandlers-proxy.vala b/src/mconnect/packethandlers-proxy.vala index cc450b1..c9af288 100644 --- a/src/mconnect/packethandlers-proxy.vala +++ b/src/mconnect/packethandlers-proxy.vala @@ -20,29 +20,29 @@ class PacketHandlersProxy : Object { - public static PacketHandlerInterfaceProxy? new_device_capability_handler( - Device dev, - string cap, - PacketHandlerInterface iface) { + public static PacketHandlerInterfaceProxy ? new_device_capability_handler ( + Device dev, + string cap, + PacketHandlerInterface iface) { - switch (iface.get_pkt_type()) { - case BatteryHandler.BATTERY: { - return new BatteryHandlerProxy.for_device_handler(dev, iface); - } - case PingHandler.PING: { - return new PingHandlerProxy.for_device_handler(dev, iface); - } - case ShareHandler.SHARE: { - return new ShareHandlerProxy.for_device_handler(dev, iface); - } - case TelephonyHandler.TELEPHONY: { - return new TelephonyHandlerProxy.for_device_handler(dev, iface); - } - default: - warning("cannot register bus handler for %s", - iface.get_pkt_type()); - break; - } - return null; - } + switch (iface.get_pkt_type ()) { + case BatteryHandler.BATTERY: { + return new BatteryHandlerProxy.for_device_handler (dev, iface); + } + case PingHandler.PING: { + return new PingHandlerProxy.for_device_handler (dev, iface); + } + case ShareHandler.SHARE: { + return new ShareHandlerProxy.for_device_handler (dev, iface); + } + case TelephonyHandler.TELEPHONY: { + return new TelephonyHandlerProxy.for_device_handler (dev, iface); + } + default: + warning ("cannot register bus handler for %s", + iface.get_pkt_type ()); + break; + } + return null; + } } \ No newline at end of file diff --git a/src/mconnect/packethandlers.vala b/src/mconnect/packethandlers.vala index f36c0e1..5b8bcbe 100644 --- a/src/mconnect/packethandlers.vala +++ b/src/mconnect/packethandlers.vala @@ -21,58 +21,61 @@ using Gee; class PacketHandlers : Object { - private HashMap _handlers; + private HashMap _handlers; - public string[] interfaces { - owned get { return _handlers.keys.to_array(); } - private set {} - } + public string[] interfaces { + owned get { + return _handlers.keys.to_array (); + } + private set { + } + } - public PacketHandlers() { - _handlers = load_handlers(); - } + public PacketHandlers () { + _handlers = load_handlers (); + } - private static HashMap load_handlers() { - HashMap hnd = - new HashMap(); + private static HashMap load_handlers () { + HashMap hnd = + new HashMap(); - var notification = NotificationHandler.instance(); - var battery = BatteryHandler.instance(); - var telephony = TelephonyHandler.instance(); - var mousepad = MousepadHandler.instance(); - var ping = PingHandler.instance(); - var share = ShareHandler.instance(); + var notification = NotificationHandler.instance (); + var battery = BatteryHandler.instance (); + var telephony = TelephonyHandler.instance (); + var mousepad = MousepadHandler.instance (); + var ping = PingHandler.instance (); + var share = ShareHandler.instance (); - hnd.@set(notification.get_pkt_type(), notification); - hnd.@set(battery.get_pkt_type(), battery); - hnd.@set(telephony.get_pkt_type(), telephony); - hnd.@set(mousepad.get_pkt_type(), mousepad); - hnd.@set(ping.get_pkt_type(), ping); - hnd.@set(share.get_pkt_type(), share); + hnd.@set (notification.get_pkt_type (), notification); + hnd.@set (battery.get_pkt_type (), battery); + hnd.@set (telephony.get_pkt_type (), telephony); + hnd.@set (mousepad.get_pkt_type (), mousepad); + hnd.@set (ping.get_pkt_type (), ping); + hnd.@set (share.get_pkt_type (), share); - return hnd; - } + return hnd; + } - /** - * SupportedCapabilityFunc: - * @capability: capability name - * @handler: packet handler - * - * User provided callback called when enabling @capability handled - * by @handler for a particular device. - */ - public delegate void SupportedCapabilityFunc(string capability, - PacketHandlerInterface handler); + /** + * SupportedCapabilityFunc: + * @capability: capability name + * @handler: packet handler + * + * User provided callback called when enabling @capability handled + * by @handler for a particular device. + */ + public delegate void SupportedCapabilityFunc (string capability, + PacketHandlerInterface handler); - public PacketHandlerInterface? get_capability_handler(string cap) { - // all handlers are singletones for now - var h = this._handlers.@get(cap); - return h; - } + public PacketHandlerInterface ? get_capability_handler (string cap) { + // all handlers are singletones for now + var h = this._handlers.@get (cap); + return h; + } - public static string to_capability(string pkttype) { - if (pkttype.has_suffix(".request")) - return pkttype.replace(".request", ""); - return pkttype; - } + public static string to_capability (string pkttype) { + if (pkttype.has_suffix (".request")) + return pkttype.replace (".request", ""); + return pkttype; + } } \ No newline at end of file diff --git a/src/mconnect/ping-proxy.vala b/src/mconnect/ping-proxy.vala index cc0abbf..26f2c1e 100644 --- a/src/mconnect/ping-proxy.vala +++ b/src/mconnect/ping-proxy.vala @@ -21,32 +21,32 @@ [DBus (name = "org.mconnect.Device.Ping")] class PingHandlerProxy : Object, PacketHandlerInterfaceProxy { - private Device device = null; - private PingHandler ping_handler = null; - - public PingHandlerProxy.for_device_handler(Device dev, - PacketHandlerInterface iface) { - this.device = dev; - this.ping_handler = (PingHandler) iface; - this.ping_handler.ping.connect(this.ping_cb); - } - - [DBus (visible = false)] - public void bus_register(DBusConnection conn, string path) throws IOError { - conn.register_object(path, this); - } - - [DBus (visible = false)] - public void bus_unregister(DBusConnection conn) throws IOError { - //conn.unregister_object(this); - } - - private void ping_cb(Device dev) { - if (this.device != dev) - return; - - ping(); - } - - public signal void ping(); + private Device device = null; + private PingHandler ping_handler = null; + + public PingHandlerProxy.for_device_handler (Device dev, + PacketHandlerInterface iface) { + this.device = dev; + this.ping_handler = (PingHandler) iface; + this.ping_handler.ping.connect (this.ping_cb); + } + + [DBus (visible = false)] + public void bus_register (DBusConnection conn, string path) throws IOError { + conn.register_object (path, this); + } + + [DBus (visible = false)] + public void bus_unregister (DBusConnection conn) throws IOError { + // conn.unregister_object(this); + } + + private void ping_cb (Device dev) { + if (this.device != dev) + return; + + ping (); + } + + public signal void ping (); } \ No newline at end of file diff --git a/src/mconnect/ping.vala b/src/mconnect/ping.vala index 1733951..42b0deb 100644 --- a/src/mconnect/ping.vala +++ b/src/mconnect/ping.vala @@ -20,38 +20,37 @@ class PingHandler : Object, PacketHandlerInterface { - public const string PING = "kdeconnect.ping"; + public const string PING = "kdeconnect.ping"; - public string get_pkt_type() { - return PING; - } + public string get_pkt_type () { + return PING; + } - private PingHandler() { + private PingHandler () { + } - } + public static PingHandler instance () { + return new PingHandler (); + } - public static PingHandler instance() { - return new PingHandler(); - } + public void use_device (Device dev) { + debug ("use device %s for ping", dev.to_string ()); + dev.message.connect (this.message); + } - public void use_device(Device dev) { - debug("use device %s for ping", dev.to_string()); - dev.message.connect(this.message); - } + public void release_device (Device dev) { + debug ("release device %s", dev.to_string ()); + dev.message.disconnect (this.message); + } - public void release_device(Device dev) { - debug("release device %s", dev.to_string()); - dev.message.disconnect(this.message); - } + public void message (Device dev, Packet pkt) { + if (pkt.pkt_type != PING) { + return; + } - public void message(Device dev, Packet pkt) { - if (pkt.pkt_type != PING) { - return; - } + GLib.message ("ping from device %s", dev.to_string ()); + ping (dev); + } - GLib.message("ping from device %s", dev.to_string()); - ping(dev); - } - - public signal void ping(Device dev); + public signal void ping (Device dev); } \ No newline at end of file diff --git a/src/mconnect/property-proxy.vala b/src/mconnect/property-proxy.vala index 3ab4778..815052a 100644 --- a/src/mconnect/property-proxy.vala +++ b/src/mconnect/property-proxy.vala @@ -24,78 +24,78 @@ */ class DBusPropertyNotifier : Object { - private DBusConnection conn = null; - private string iface = ""; - private string path = ""; - private VariantBuilder builder = null; - private uint timeout_src = 0; + private DBusConnection conn = null; + private string iface = ""; + private string path = ""; + private VariantBuilder builder = null; + private uint timeout_src = 0; - public const uint TIMEOUT = 300; + public const uint TIMEOUT = 300; - public DBusPropertyNotifier(DBusConnection conn, - string iface, - string path) { - this.conn = conn; - this.iface = iface; - this.path = path; - } + public DBusPropertyNotifier (DBusConnection conn, + string iface, + string path) { + this.conn = conn; + this.iface = iface; + this.path = path; + } - /** - * queue_property_change: - * - * @name: property name (will be automatically capitalized if needed) - * @val: Variant holding property value - * - * This method will queue up property notifications for sending. By default - * it waits @TIMEOUT ms before sending the actual signal. - */ - public void queue_property_change(string name, Variant val) { - if (this.builder == null) { - this.builder = new VariantBuilder(VariantType.ARRAY); - } + /** + * queue_property_change: + * + * @name: property name (will be automatically capitalized if needed) + * @val: Variant holding property value + * + * This method will queue up property notifications for sending. By default + * it waits @TIMEOUT ms before sending the actual signal. + */ + public void queue_property_change (string name, Variant val) { + if (this.builder == null) { + this.builder = new VariantBuilder (VariantType.ARRAY); + } - string nm = name; - if (name.get_char(0).islower()) { - nm = name.get_char(0).toupper().to_string() + name.substring(1); - } + string nm = name; + if (name.get_char (0).islower ()) { + nm = name.get_char (0).toupper ().to_string () + name.substring (1); + } - this.builder.add("{sv}", nm, val); + this.builder.add ("{sv}", nm, val); - if (this.timeout_src == 0) { - this.timeout_src = Timeout.add(300, - this.send_property_change); - } - } + if (this.timeout_src == 0) { + this.timeout_src = Timeout.add (300, + this.send_property_change); + } + } - /** - * send_property_change: - * - * Send out actual PropertiesChanged signals - */ - private bool send_property_change() { - this.timeout_src = 0; + /** + * send_property_change: + * + * Send out actual PropertiesChanged signals + */ + private bool send_property_change () { + this.timeout_src = 0; - if (this.builder == null) - return false;; + if (this.builder == null) + return false; ; try { - var invalid_builder = new VariantBuilder(new VariantType ("as")); + var invalid_builder = new VariantBuilder (new VariantType ("as")); - this.conn.emit_signal(null, - this.path, - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - new Variant ("(sa{sv}as)", - this.iface, - builder, - invalid_builder) - ); + this.conn.emit_signal (null, + this.path, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + new Variant ("(sa{sv}as)", + this.iface, + builder, + invalid_builder) + ); } catch (Error e) { - warning("%s\n", e.message); + warning ("%s\n", e.message); } - this.builder = null; + this.builder = null; - return false; - } + return false; + } } \ No newline at end of file diff --git a/src/mconnect/share-proxy.vala b/src/mconnect/share-proxy.vala index 998b408..3d8be82 100644 --- a/src/mconnect/share-proxy.vala +++ b/src/mconnect/share-proxy.vala @@ -21,35 +21,35 @@ [DBus (name = "org.mconnect.Device.Share")] class ShareHandlerProxy : Object, PacketHandlerInterfaceProxy { - private Device device = null; - private ShareHandler share_handler = null; - - public ShareHandlerProxy.for_device_handler(Device dev, - PacketHandlerInterface iface) { - this.device = dev; - this.share_handler = (ShareHandler) iface; - } - - [DBus (visible = false)] - public void bus_register(DBusConnection conn, string path) throws IOError { - conn.register_object(path, this); - } - - [DBus (visible = false)] - public void bus_unregister(DBusConnection conn) throws IOError { - //conn.unregister_object(this); - } - - public void share_file(string path) throws IOError { - this.share_handler.share_file(this.device, path); - } - - public void share_url(string url) throws IOError { - debug("share url %s", url); - this.share_handler.share_url(this.device, url); - } - - public void share_text(string text) throws IOError { - this.share_handler.share_text(this.device, text); - } + private Device device = null; + private ShareHandler share_handler = null; + + public ShareHandlerProxy.for_device_handler (Device dev, + PacketHandlerInterface iface) { + this.device = dev; + this.share_handler = (ShareHandler) iface; + } + + [DBus (visible = false)] + public void bus_register (DBusConnection conn, string path) throws IOError { + conn.register_object (path, this); + } + + [DBus (visible = false)] + public void bus_unregister (DBusConnection conn) throws IOError { + // conn.unregister_object(this); + } + + public void share_file (string path) throws IOError { + this.share_handler.share_file (this.device, path); + } + + public void share_url (string url) throws IOError { + debug ("share url %s", url); + this.share_handler.share_url (this.device, url); + } + + public void share_text (string text) throws IOError { + this.share_handler.share_text (this.device, text); + } } \ No newline at end of file diff --git a/src/mconnect/share.vala b/src/mconnect/share.vala index 35acf49..af9f6c4 100644 --- a/src/mconnect/share.vala +++ b/src/mconnect/share.vala @@ -18,192 +18,192 @@ class ShareHandler : Object, PacketHandlerInterface { - public const string SHARE = "kdeconnect.share.request"; - public const string SHARE_PKT = "kdeconnect.share"; - private static string DOWNLOADS = null; - - public void use_device(Device dev) { - debug("use device %s for sharing", dev.to_string()); - dev.message.connect(this.message); - } - - private ShareHandler() { - } - - public static ShareHandler instance() { - if (ShareHandler.DOWNLOADS == null) { - - ShareHandler.DOWNLOADS = Path.build_filename( - Environment.get_user_special_dir(UserDirectory.DOWNLOAD), - "mconnect"); - - if (DirUtils.create_with_parents(ShareHandler.DOWNLOADS, - 0700) == -1) { - warning("failed to create downloads directory: %s", - Posix.strerror(Posix.errno)); - } - } - - info("downloads will be saved to %s", ShareHandler.DOWNLOADS); - return new ShareHandler(); - } - - private static string make_downloads_path(string name) { - return Path.build_filename(ShareHandler.DOWNLOADS, name); - } - - public string get_pkt_type() { - return SHARE; - } - - public void release_device(Device dev) { - debug("release device %s", dev.to_string()); - dev.message.disconnect(this.message); - } - - private void message(Device dev, Packet pkt) { - if (pkt.pkt_type != SHARE_PKT && pkt.pkt_type != SHARE) { - return; - } - - if (pkt.body.has_member("filename")) { - this.handle_file(dev, pkt); - } else if (pkt.body.has_member("url")) { - this.handle_url(dev, pkt); - } else if (pkt.body.has_member("text")) { - this.handle_text(dev, pkt); - } - } - - private void handle_file(Device dev, Packet pkt) { - if (pkt.payload == null) { - warning("missing payload info"); - return; - } - - string name = pkt.body.get_string_member("filename"); - debug("file: %s size: %s", name, format_size(pkt.payload.size)); - - var t = new DownloadTransfer( - dev, - new InetSocketAddress(dev.host, - (uint16) pkt.payload.port), - pkt.payload.size, - make_downloads_path(name)); - - Core.instance().transfer_manager.push_job(t); - - t.start_async.begin(); - } - - private void handle_url(Device dev, Packet pkt) { - var url_msg = pkt.body.get_string_member("url"); - - var urls = Utils.find_urls(url_msg); - if (urls.length > 0) { - var url = urls[0]; - debug("got URL: %s, launching...", url); - Utils.show_own_notification("Launching shared URL", - dev.device_name); - AppInfo.launch_default_for_uri(url, null); - } - } - - private void handle_text(Device dev, Packet pkt) { - var text = pkt.body.get_string_member("text"); - debug("shared text '%s'", text); - var display = Gdk.Display.get_default(); - if (display != null) { - var cb = Gtk.Clipboard.get_default(display); - cb.set_text(text, -1); - Utils.show_own_notification("Text copied to clipboard", - dev.device_name); - } - } - - private Packet make_share_packet(string name, string data) { - var builder = new Json.Builder(); - builder.begin_object(); - builder.set_member_name(name); - builder.add_string_value(data); - builder.end_object(); - return new Packet(SHARE, - builder.get_root().get_object()); - } - - private Packet make_file_share_packet(string filename, uint64 size, - uint16 port) { - - var builder = new Json.Builder(); - builder.begin_object(); - builder.set_member_name("filename"); - builder.add_string_value(filename); - builder.end_object(); - - var pkt = new Packet(SHARE, - builder.get_root().get_object()); - pkt.payload = Packet.Payload(){ - size=size, - port=port - }; - return pkt; - } - - public void share_url(Device dev, string url) { - debug("share url %s to device %s", url, dev.to_string()); - - dev.send(make_share_packet("url", url)); - } - - public void share_text(Device dev, string text) { - debug("share text %s to device %s", text, dev.to_string()); - - dev.send(make_share_packet("text", text)); - } - - public void share_file(Device dev, string path) { - debug("share file %s to device %s", path, dev.to_string()); - - var file = File.new_for_path(path); - uint64 size = 0; - try { - var fi = file.query_info(FileAttribute.STANDARD_SIZE, - FileQueryInfoFlags.NONE); - size = fi.get_size(); - } catch (Error e) { - warning("failed to obtain file size: %s", e.message); - return; - } - - debug("file size: %llu", size); - - if (size == 0) { - warning("trying to share empty file %s", path); - return; - } - - FileInputStream input; - try { - input = file.read(); - } catch (Error e) { - warning("failed to open source file at path %s: %s", - file.get_path(), e.message); - throw e; - } - - uint16 port; - var listener = Core.instance().transfer_manager.make_listener(out port); - if (listener == null) { - warning("coult not allodate a listener"); - return; - } - debug("allocated listener on port %u", port); - - var t = new UploadTransfer(dev, listener, input, size); - - Core.instance().transfer_manager.push_job(t); - - t.start_async.begin(); - dev.send(make_file_share_packet(file.get_basename(), size, port)); - } + public const string SHARE = "kdeconnect.share.request"; + public const string SHARE_PKT = "kdeconnect.share"; + private static string DOWNLOADS = null; + + public void use_device (Device dev) { + debug ("use device %s for sharing", dev.to_string ()); + dev.message.connect (this.message); + } + + private ShareHandler () { + } + + public static ShareHandler instance () { + if (ShareHandler.DOWNLOADS == null) { + + ShareHandler.DOWNLOADS = Path.build_filename ( + Environment.get_user_special_dir (UserDirectory.DOWNLOAD), + "mconnect"); + + if (DirUtils.create_with_parents (ShareHandler.DOWNLOADS, + 0700) == -1) { + warning ("failed to create downloads directory: %s", + Posix.strerror (Posix.errno)); + } + } + + info ("downloads will be saved to %s", ShareHandler.DOWNLOADS); + return new ShareHandler (); + } + + private static string make_downloads_path (string name) { + return Path.build_filename (ShareHandler.DOWNLOADS, name); + } + + public string get_pkt_type () { + return SHARE; + } + + public void release_device (Device dev) { + debug ("release device %s", dev.to_string ()); + dev.message.disconnect (this.message); + } + + private void message (Device dev, Packet pkt) { + if (pkt.pkt_type != SHARE_PKT && pkt.pkt_type != SHARE) { + return; + } + + if (pkt.body.has_member ("filename")) { + this.handle_file (dev, pkt); + } else if (pkt.body.has_member ("url")) { + this.handle_url (dev, pkt); + } else if (pkt.body.has_member ("text")) { + this.handle_text (dev, pkt); + } + } + + private void handle_file (Device dev, Packet pkt) { + if (pkt.payload == null) { + warning ("missing payload info"); + return; + } + + string name = pkt.body.get_string_member ("filename"); + debug ("file: %s size: %s", name, format_size (pkt.payload.size)); + + var t = new DownloadTransfer ( + dev, + new InetSocketAddress (dev.host, + (uint16) pkt.payload.port), + pkt.payload.size, + make_downloads_path (name)); + + Core.instance ().transfer_manager.push_job (t); + + t.start_async.begin (); + } + + private void handle_url (Device dev, Packet pkt) { + var url_msg = pkt.body.get_string_member ("url"); + + var urls = Utils.find_urls (url_msg); + if (urls.length > 0) { + var url = urls[0]; + debug ("got URL: %s, launching...", url); + Utils.show_own_notification ("Launching shared URL", + dev.device_name); + AppInfo.launch_default_for_uri (url, null); + } + } + + private void handle_text (Device dev, Packet pkt) { + var text = pkt.body.get_string_member ("text"); + debug ("shared text '%s'", text); + var display = Gdk.Display.get_default (); + if (display != null) { + var cb = Gtk.Clipboard.get_default (display); + cb.set_text (text, -1); + Utils.show_own_notification ("Text copied to clipboard", + dev.device_name); + } + } + + private Packet make_share_packet (string name, string data) { + var builder = new Json.Builder (); + builder.begin_object (); + builder.set_member_name (name); + builder.add_string_value (data); + builder.end_object (); + return new Packet (SHARE, + builder.get_root ().get_object ()); + } + + private Packet make_file_share_packet (string filename, uint64 size, + uint16 port) { + + var builder = new Json.Builder (); + builder.begin_object (); + builder.set_member_name ("filename"); + builder.add_string_value (filename); + builder.end_object (); + + var pkt = new Packet (SHARE, + builder.get_root ().get_object ()); + pkt.payload = Packet.Payload () { + size = size, + port = port + }; + return pkt; + } + + public void share_url (Device dev, string url) { + debug ("share url %s to device %s", url, dev.to_string ()); + + dev.send (make_share_packet ("url", url)); + } + + public void share_text (Device dev, string text) { + debug ("share text %s to device %s", text, dev.to_string ()); + + dev.send (make_share_packet ("text", text)); + } + + public void share_file (Device dev, string path) { + debug ("share file %s to device %s", path, dev.to_string ()); + + var file = File.new_for_path (path); + uint64 size = 0; + try { + var fi = file.query_info (FileAttribute.STANDARD_SIZE, + FileQueryInfoFlags.NONE); + size = fi.get_size (); + } catch (Error e) { + warning ("failed to obtain file size: %s", e.message); + return; + } + + debug ("file size: %llu", size); + + if (size == 0) { + warning ("trying to share empty file %s", path); + return; + } + + FileInputStream input; + try { + input = file.read (); + } catch (Error e) { + warning ("failed to open source file at path %s: %s", + file.get_path (), e.message); + throw e; + } + + uint16 port; + var listener = Core.instance ().transfer_manager.make_listener (out port); + if (listener == null) { + warning ("coult not allodate a listener"); + return; + } + debug ("allocated listener on port %u", port); + + var t = new UploadTransfer (dev, listener, input, size); + + Core.instance ().transfer_manager.push_job (t); + + t.start_async.begin (); + dev.send (make_file_share_packet (file.get_basename (), size, port)); + } } \ No newline at end of file diff --git a/src/mconnect/telephony-proxy.vala b/src/mconnect/telephony-proxy.vala index 817edba..a1da4c3 100644 --- a/src/mconnect/telephony-proxy.vala +++ b/src/mconnect/telephony-proxy.vala @@ -19,26 +19,26 @@ [DBus (name = "org.mconnect.Device.Telephony")] class TelephonyHandlerProxy : Object, PacketHandlerInterfaceProxy { - private Device device = null; - private TelephonyHandler telephony = null; + private Device device = null; + private TelephonyHandler telephony = null; - public TelephonyHandlerProxy.for_device_handler(Device dev, - PacketHandlerInterface iface) { - this.device = dev; - this.telephony = (TelephonyHandler) iface; - } + public TelephonyHandlerProxy.for_device_handler (Device dev, + PacketHandlerInterface iface) { + this.device = dev; + this.telephony = (TelephonyHandler) iface; + } - [DBus (visible = false)] - public void bus_register(DBusConnection conn, string path) throws IOError { - conn.register_object(path, this); - } + [DBus (visible = false)] + public void bus_register (DBusConnection conn, string path) throws IOError { + conn.register_object (path, this); + } - [DBus (visible = false)] - public void bus_unregister(DBusConnection conn) throws IOError { - // conn.unregister_object(this); - } + [DBus (visible = false)] + public void bus_unregister (DBusConnection conn) throws IOError { + // conn.unregister_object(this); + } - public void send_sms(string number, string message) { - this.telephony.send_sms(this.device, number, message); - } + public void send_sms (string number, string message) { + this.telephony.send_sms (this.device, number, message); + } } \ No newline at end of file diff --git a/src/mconnect/telephony.vala b/src/mconnect/telephony.vala index 12c4eff..dc862ee 100644 --- a/src/mconnect/telephony.vala +++ b/src/mconnect/telephony.vala @@ -1,4 +1,4 @@ - /* ex:ts=4:sw=4:sts=4:et */ +/* ex:ts=4:sw=4:sts=4:et */ /* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify @@ -21,109 +21,107 @@ using Mconn; class TelephonyHandler : Object, PacketHandlerInterface { - public const string TELEPHONY = "kdeconnect.telephony"; - public const string SMS_REQUEST = "kdeconnect.sms.request"; - - public string get_pkt_type() { - return TELEPHONY; - } - - private TelephonyHandler() { - - } - - public static TelephonyHandler instance() { - return new TelephonyHandler(); - } - - public void use_device(Device dev) { - dev.message.connect(this.message); - } - - public void release_device(Device dev) { - dev.message.disconnect(this.message); - } - - public void message(Device dev, Packet pkt) { - if (pkt.pkt_type != TELEPHONY) { - return; - } - - debug("got telephony packet"); - - if (pkt.body.has_member("phoneNumber") == false || - pkt.body.has_member("event") == false) - return; - - string number = pkt.body.get_string_member("phoneNumber"); - string ev = pkt.body.get_string_member("event"); - - // string ticker = convert_to_utf8(raw_ticker); - GLib.message("call from %s, status %s", number, ev); - - // handle only missed call and ringing events - const string[] accepted_events = {"ringing", "missedCall"}; - - if (ev in accepted_events) { - string summary = "Other event"; - - if (ev == "ringing") - summary = "Incoming call"; - if (ev == "missedCall") - summary = "Missed call"; - - // check if ringing was cancelled - if (ev == "missedCall" && pkt.body.has_member("isCancel")) { - bool cancelled = pkt.body.get_boolean_member("isCancel"); - if (cancelled == true) { - debug("call cancelled"); - return; - } - } - - // telephony packets have no time information - var time = new DateTime.now_local(); - number = "%s %s".printf(time.format("%X"), number); - - var notif = new Notify.Notification(summary, number, - "phone"); - try { - notif.show(); - } catch (Error e) { - critical("failed to show notification: %s", e.message); - } - - } - } - - /** - * make_sms_packet: - * @number: recipient's number - * @message: message - * - * @return allocated packet - */ - private Packet make_sms_packet(string number, string message) { - var builder = new Json.Builder(); - builder.begin_object(); - builder.set_member_name("sendSms"); - builder.add_boolean_value(true); - builder.set_member_name("phoneNumber"); - builder.add_string_value(number); - builder.set_member_name("messageBody"); - builder.add_string_value(message); - builder.end_object(); - - return new Packet(SMS_REQUEST, - builder.get_root().get_object()); - } - - /** - * send_sms: - * - * Reques to send an SMS to @number with message @message. - */ - public void send_sms(Device dev, string number, string message) { - dev.send(make_sms_packet(number, message)); - } + public const string TELEPHONY = "kdeconnect.telephony"; + public const string SMS_REQUEST = "kdeconnect.sms.request"; + + public string get_pkt_type () { + return TELEPHONY; + } + + private TelephonyHandler () { + } + + public static TelephonyHandler instance () { + return new TelephonyHandler (); + } + + public void use_device (Device dev) { + dev.message.connect (this.message); + } + + public void release_device (Device dev) { + dev.message.disconnect (this.message); + } + + public void message (Device dev, Packet pkt) { + if (pkt.pkt_type != TELEPHONY) { + return; + } + + debug ("got telephony packet"); + + if (pkt.body.has_member ("phoneNumber") == false || + pkt.body.has_member ("event") == false) + return; + + string number = pkt.body.get_string_member ("phoneNumber"); + string ev = pkt.body.get_string_member ("event"); + + // string ticker = convert_to_utf8(raw_ticker); + GLib.message ("call from %s, status %s", number, ev); + + // handle only missed call and ringing events + const string[] accepted_events = { "ringing", "missedCall" }; + + if (ev in accepted_events) { + string summary = "Other event"; + + if (ev == "ringing") + summary = "Incoming call"; + if (ev == "missedCall") + summary = "Missed call"; + + // check if ringing was cancelled + if (ev == "missedCall" && pkt.body.has_member ("isCancel")) { + bool cancelled = pkt.body.get_boolean_member ("isCancel"); + if (cancelled == true) { + debug ("call cancelled"); + return; + } + } + + // telephony packets have no time information + var time = new DateTime.now_local (); + number = "%s %s".printf (time.format ("%X"), number); + + var notif = new Notify.Notification (summary, number, + "phone"); + try { + notif.show (); + } catch (Error e) { + critical ("failed to show notification: %s", e.message); + } + } + } + + /** + * make_sms_packet: + * @number: recipient's number + * @message: message + * + * @return allocated packet + */ + private Packet make_sms_packet (string number, string message) { + var builder = new Json.Builder (); + builder.begin_object (); + builder.set_member_name ("sendSms"); + builder.add_boolean_value (true); + builder.set_member_name ("phoneNumber"); + builder.add_string_value (number); + builder.set_member_name ("messageBody"); + builder.add_string_value (message); + builder.end_object (); + + return new Packet (SMS_REQUEST, + builder.get_root ().get_object ()); + } + + /** + * send_sms: + * + * Reques to send an SMS to @number with message @message. + */ + public void send_sms (Device dev, string number, string message) { + dev.send (make_sms_packet (number, message)); + } } \ No newline at end of file diff --git a/src/mconnect/transfer-download.vala b/src/mconnect/transfer-download.vala index 90deda5..061f3ac 100644 --- a/src/mconnect/transfer-download.vala +++ b/src/mconnect/transfer-download.vala @@ -18,170 +18,170 @@ class DownloadTransfer : TransferInterface, Object { - private InetSocketAddress isa = null; - private File file = null; - private FileOutputStream foutstream = null; - private Cancellable cancellable = null; - private SocketConnection conn = null; - private TlsConnection tls_conn = null; - public uint64 size = 0; - public uint64 transferred = 0; - public string destination = ""; - private IOCopyJob job = null; - private Device device = null; - - public DownloadTransfer(Device dev, InetSocketAddress isa, - uint64 size, string dest) { - this.isa = isa; - this.cancellable = new Cancellable(); - this.destination = dest; - this.size = size; - this.device = dev; - } - - public async bool start_async() { - try { - this.file = File.new_for_path(this.destination + ".part"); - this.foutstream = this.file.replace(null, false, - FileCreateFlags.PRIVATE | FileCreateFlags.REPLACE_DESTINATION); - } catch (Error e) { - warning("failed to open destination path %s: %s", - this.destination, e.message); - return false; - } - - debug("start transfer from %s:%u", - this.isa.address.to_string(), this.isa.port); - var client = new SocketClient(); - - try { - this.conn = yield client.connect_async(this.isa); - debug("connected"); - } catch (Error e) { - var err ="failed to connect: %s".printf(e.message); - warning(err); - this.cleanup_error(err); - return false; - } - - var sock = this.conn.get_socket(); - Utils.socket_set_keepalive(sock); - - // enable TLS - this.tls_conn = Utils.make_tls_connection(this.conn, - Core.instance().certificate, - this.device.certificate, - Utils.TlsConnectionMode.CLIENT); - try { - debug("attempt TLS handshake"); - var tls_res = yield this.tls_conn.handshake_async(); - debug("TLS handshake complete"); - } catch (Error e) { - var err ="TLS handshake failed: %s".printf(e.message); - warning(err); - this.cleanup_error(err); - return false; - } - - this.start_transfer(); - return true; - } - - private void start_transfer() { - debug("connected, start transfer"); - this.job = new IOCopyJob(this.tls_conn.input_stream, - this.foutstream); - this.job.progress.connect((t, done) => { - int percent = (int) (100.0 * ((double)done / (double)this.size)); - debug("progress: %s/%s %d%%", - format_size(done), format_size(this.size), percent); - this.transferred = done; - }); - - this.started(); - - this.job.start_async.begin(this.cancellable, - this.job_complete); - } - - private void job_complete(Object? obj, AsyncResult res) { - info("transfer finished"); - try { - var rcvd_bytes = this.job.start_async.end(res); - debug("transfer done, got %s", format_size(rcvd_bytes)); - - this.cleanup_success(); - - } catch (Error err) { - warning("transfer failed: %s", err.message); - - this.cleanup_error(err.message); - } - } - - private void cleanup() { - if (this.foutstream != null) { - try { - this.foutstream.close(); - } catch (IOError e) { - warning("failed to close file output: %s", - e.message); - } - } - - if (this.tls_conn != null) { - try { - this.tls_conn.close(); - } catch (IOError e) { - warning("failed to close TLS connection: %s", - e.message); - } - } - if (this.conn != null) { - try { - this.conn.close(); - } catch (IOError e) { - warning("failed to close connection: %s", - e.message); - } - } - - this.file = null; - this.foutstream = null; - this.conn = null; - this.tls_conn = null; - this.job = null; - } - - private void cleanup_error(string reason) { - - this.file.@delete(); - - this.cleanup(); - - this.error(reason); - } - - private void cleanup_success() { - try { - var dest = File.new_for_path(this.destination); - this.file.move(dest, FileCopyFlags.OVERWRITE); - - this.cleanup(); - - this.finished(); - - } catch (Error e) { - var err = "failed to rename temporary file %s to %s: %s".printf(this.file.get_path(), - this.destination, - e.message); - warning(err); - this.cleanup_error(err); - } - } - - public void cancel() { - debug("cancel called"); - this.cancellable.cancel(); - } + private InetSocketAddress isa = null; + private File file = null; + private FileOutputStream foutstream = null; + private Cancellable cancellable = null; + private SocketConnection conn = null; + private TlsConnection tls_conn = null; + public uint64 size = 0; + public uint64 transferred = 0; + public string destination = ""; + private IOCopyJob job = null; + private Device device = null; + + public DownloadTransfer (Device dev, InetSocketAddress isa, + uint64 size, string dest) { + this.isa = isa; + this.cancellable = new Cancellable (); + this.destination = dest; + this.size = size; + this.device = dev; + } + + public async bool start_async () { + try { + this.file = File.new_for_path (this.destination + ".part"); + this.foutstream = this.file.replace (null, false, + FileCreateFlags.PRIVATE | FileCreateFlags.REPLACE_DESTINATION); + } catch (Error e) { + warning ("failed to open destination path %s: %s", + this.destination, e.message); + return false; + } + + debug ("start transfer from %s:%u", + this.isa.address.to_string (), this.isa.port); + var client = new SocketClient (); + + try { + this.conn = yield client.connect_async (this.isa); + + debug ("connected"); + } catch (Error e) { + var err = "failed to connect: %s".printf (e.message); + warning (err); + this.cleanup_error (err); + return false; + } + + var sock = this.conn.get_socket (); + Utils.socket_set_keepalive (sock); + + // enable TLS + this.tls_conn = Utils.make_tls_connection (this.conn, + Core.instance ().certificate, + this.device.certificate, + Utils.TlsConnectionMode.CLIENT); + try { + debug ("attempt TLS handshake"); + var tls_res = yield this.tls_conn.handshake_async (); + + debug ("TLS handshake complete"); + } catch (Error e) { + var err = "TLS handshake failed: %s".printf (e.message); + warning (err); + this.cleanup_error (err); + return false; + } + + this.start_transfer (); + return true; + } + + private void start_transfer () { + debug ("connected, start transfer"); + this.job = new IOCopyJob (this.tls_conn.input_stream, + this.foutstream); + this.job.progress.connect ((t, done) => { + int percent = (int) (100.0 * ((double) done / (double) this.size)); + debug ("progress: %s/%s %d%%", + format_size (done), format_size (this.size), percent); + this.transferred = done; + }); + + this.started (); + + this.job.start_async.begin (this.cancellable, + this.job_complete); + } + + private void job_complete (Object ? obj, AsyncResult res) { + info ("transfer finished"); + try { + var rcvd_bytes = this.job.start_async.end (res); + debug ("transfer done, got %s", format_size (rcvd_bytes)); + + this.cleanup_success (); + } catch (Error err) { + warning ("transfer failed: %s", err.message); + + this.cleanup_error (err.message); + } + } + + private void cleanup () { + if (this.foutstream != null) { + try { + this.foutstream.close (); + } catch (IOError e) { + warning ("failed to close file output: %s", + e.message); + } + } + + if (this.tls_conn != null) { + try { + this.tls_conn.close (); + } catch (IOError e) { + warning ("failed to close TLS connection: %s", + e.message); + } + } + if (this.conn != null) { + try { + this.conn.close (); + } catch (IOError e) { + warning ("failed to close connection: %s", + e.message); + } + } + + this.file = null; + this.foutstream = null; + this.conn = null; + this.tls_conn = null; + this.job = null; + } + + private void cleanup_error (string reason) { + + this.file.@delete (); + + this.cleanup (); + + this.error (reason); + } + + private void cleanup_success () { + try { + var dest = File.new_for_path (this.destination); + this.file.move (dest, FileCopyFlags.OVERWRITE); + + this.cleanup (); + + this.finished (); + } catch (Error e) { + var err = "failed to rename temporary file %s to %s: %s".printf (this.file.get_path (), + this.destination, + e.message); + warning (err); + this.cleanup_error (err); + } + } + + public void cancel () { + debug ("cancel called"); + this.cancellable.cancel (); + } } \ No newline at end of file diff --git a/src/mconnect/transfer-interface.vala b/src/mconnect/transfer-interface.vala index 3ccad0f..c3cc018 100644 --- a/src/mconnect/transfer-interface.vala +++ b/src/mconnect/transfer-interface.vala @@ -18,12 +18,11 @@ interface TransferInterface : Object { - public abstract async bool start_async(); + public abstract async bool start_async (); - public abstract void cancel(); + public abstract void cancel (); - public signal void started(); - public signal void finished(); - public signal void error(string reason); - -} + public signal void started (); + public signal void finished (); + public signal void error (string reason); +} \ No newline at end of file diff --git a/src/mconnect/transfer-manager-proxy.vala b/src/mconnect/transfer-manager-proxy.vala index 8a99a55..579a229 100644 --- a/src/mconnect/transfer-manager-proxy.vala +++ b/src/mconnect/transfer-manager-proxy.vala @@ -21,92 +21,91 @@ using Gee; [DBus (name = "org.mconnect.TransferManager")] class TransferManagerDBusProxy : Object { - private TransferManager manager; - private DBusConnection bus; - - private int job_idx = 0; - private const string DBUS_PATH = "/org/mconnect/transfer"; - - private HashMap jobs; - - public TransferManagerDBusProxy.with_manager(DBusConnection conn, - TransferManager manager) { - this.jobs = new HashMap(); - this.bus = conn; - - manager.new_transfer.connect(this.handle_new_transfer); - } - - [DBus (visible = false)] - public void publish() throws IOError { - assert(this.bus != null); - - this.bus.register_object(DBUS_PATH, this); - } - - /** - * list_jobs: - * - * Returns a list of DBus paths of all known transfer jobs - */ - public ObjectPath[] list_jobs() { - ObjectPath[] jobs = {}; - - foreach (var path in this.jobs.keys) { - jobs += new ObjectPath(path); - } - return jobs; - } - - - private void handle_new_transfer(Object? mgr, TransferInterface job) { - var path = make_transfer_path(); - var tproxy = new TransferDBusProxy.for_transfer_with_path(job, - new ObjectPath(path)); - - this.jobs.@set(path, tproxy); - tproxy.bus_register(this.bus); - job.started.connect((_) => { - this.transfer_started(path); - }); - job.finished.connect((o) => { - this.handle_transfer_done(path); - }); - job.error.connect((o, err) => { - this.handle_transfer_failed(path, err); - }); - } - - private string make_transfer_path() { - var path = "/org/mconnect/transfer/%d".printf(this.job_idx); - - // bump jobs index - this.job_idx++; - - return path; - } - - private void handle_transfer_done(string path) { - // var jp = this.find_proxy_for_job(TransferInterface(obj)); - var jp = this.jobs.@get(path); - assert(jp != null); - jp.bus_unregister(this.bus); - - this.transfer_finished(path); - } - - private void handle_transfer_failed(string path, string err) { - // var jp = this.find_proxy_for_job(TransferInterface(obj)); - var jp = this.jobs.@get(path); - assert(jp != null); - jp.bus_unregister(this.bus); - - this.transfer_failed(path, err); - } - - public signal void transfer_finished(string path); - - public signal void transfer_failed(string path, string reason); - - public signal void transfer_started(string path); -} + private TransferManager manager; + private DBusConnection bus; + + private int job_idx = 0; + private const string DBUS_PATH = "/org/mconnect/transfer"; + + private HashMap jobs; + + public TransferManagerDBusProxy.with_manager (DBusConnection conn, + TransferManager manager) { + this.jobs = new HashMap(); + this.bus = conn; + + manager.new_transfer.connect (this.handle_new_transfer); + } + + [DBus (visible = false)] + public void publish () throws IOError { + assert (this.bus != null); + + this.bus.register_object (DBUS_PATH, this); + } + + /** + * list_jobs: + * + * Returns a list of DBus paths of all known transfer jobs + */ + public ObjectPath[] list_jobs () { + ObjectPath[] jobs = {}; + + foreach (var path in this.jobs.keys) { + jobs += new ObjectPath (path); + } + return jobs; + } + + private void handle_new_transfer (Object ? mgr, TransferInterface job) { + var path = make_transfer_path (); + var tproxy = new TransferDBusProxy.for_transfer_with_path (job, + new ObjectPath (path)); + + this.jobs.@set (path, tproxy); + tproxy.bus_register (this.bus); + job.started.connect ((_) => { + this.transfer_started (path); + }); + job.finished.connect ((o) => { + this.handle_transfer_done (path); + }); + job.error.connect ((o, err) => { + this.handle_transfer_failed (path, err); + }); + } + + private string make_transfer_path () { + var path = "/org/mconnect/transfer/%d".printf (this.job_idx); + + // bump jobs index + this.job_idx++; + + return path; + } + + private void handle_transfer_done (string path) { + // var jp = this.find_proxy_for_job(TransferInterface(obj)); + var jp = this.jobs.@get (path); + assert (jp != null); + jp.bus_unregister (this.bus); + + this.transfer_finished (path); + } + + private void handle_transfer_failed (string path, string err) { + // var jp = this.find_proxy_for_job(TransferInterface(obj)); + var jp = this.jobs.@get (path); + assert (jp != null); + jp.bus_unregister (this.bus); + + this.transfer_failed (path, err); + } + + public signal void transfer_finished (string path); + + public signal void transfer_failed (string path, string reason); + + public signal void transfer_started (string path); +} \ No newline at end of file diff --git a/src/mconnect/transfer-manager.vala b/src/mconnect/transfer-manager.vala index 48101a6..675a223 100644 --- a/src/mconnect/transfer-manager.vala +++ b/src/mconnect/transfer-manager.vala @@ -18,39 +18,38 @@ class TransferManager : Object { - public const uint16 PORT_MIN = 9970; - public const uint16 PORT_MAX = 9975; + public const uint16 PORT_MIN = 9970; + public const uint16 PORT_MAX = 9975; - public signal void new_transfer(TransferInterface job); + public signal void new_transfer (TransferInterface job); - public TransferManager() { + public TransferManager () { + } - } + public void push_job (TransferInterface job) { + debug ("new transfer job"); + new_transfer (job); + } - public void push_job(TransferInterface job) { - debug("new transfer job"); - new_transfer(job); - } - - public SocketService? make_listener(out uint16 listen_port) { - var ss = new SocketService(); - for (var port = PORT_MIN; port <= PORT_MAX; port++) { - var added = false; - try { - added = ss.add_inet_port(port, null); - } catch (Error e) { - if (e is IOError.ADDRESS_IN_USE) { - warning("port %u in use, trying another", port); - } - } - if (added == true) { - debug("allocated listener on port %u", port); - listen_port = port; - return ss; - } - } - ss.close(); - warning("could not find a free port to listen on"); - return null; - } + public SocketService ? make_listener (out uint16 listen_port) { + var ss = new SocketService (); + for (var port = PORT_MIN; port <= PORT_MAX; port++) { + var added = false; + try { + added = ss.add_inet_port (port, null); + } catch (Error e) { + if (e is IOError.ADDRESS_IN_USE) { + warning ("port %u in use, trying another", port); + } + } + if (added == true) { + debug ("allocated listener on port %u", port); + listen_port = port; + return ss; + } + } + ss.close (); + warning ("could not find a free port to listen on"); + return null; + } } \ No newline at end of file diff --git a/src/mconnect/transfer-proxy.vala b/src/mconnect/transfer-proxy.vala index 61f463b..1fdce0e 100644 --- a/src/mconnect/transfer-proxy.vala +++ b/src/mconnect/transfer-proxy.vala @@ -17,36 +17,38 @@ */ [DBus (name = "org.mconnect.Transfer")] -class TransferDBusProxy: Object { +class TransferDBusProxy : Object { - [DBus (visible = false)] - public TransferInterface transfer { get; private set; default = null; } + [DBus (visible = false)] + public TransferInterface transfer { + get; private set; default = null; + } - private ObjectPath object_path = null; - private uint register_id = 0; + private ObjectPath object_path = null; + private uint register_id = 0; - public TransferDBusProxy.for_transfer_with_path(TransferInterface transfer, - ObjectPath path) { - this.transfer = transfer; - this.object_path = path; - } + public TransferDBusProxy.for_transfer_with_path (TransferInterface transfer, + ObjectPath path) { + this.transfer = transfer; + this.object_path = path; + } - [DBus (visible = false)] - public void bus_register(DBusConnection conn) { - debug("register transfer at path %s", this.object_path.to_string()); - this.register_id = conn.register_object(this.object_path, this); - } + [DBus (visible = false)] + public void bus_register (DBusConnection conn) { + debug ("register transfer at path %s", this.object_path.to_string ()); + this.register_id = conn.register_object (this.object_path, this); + } - [DBus (visible = false)] - public void bus_unregister(DBusConnection conn) { - if (this.register_id != 0) { - debug("unregister transfer at path %s", this.object_path.to_string()); - conn.unregister_object(this.register_id); - } - } + [DBus (visible = false)] + public void bus_unregister (DBusConnection conn) { + if (this.register_id != 0) { + debug ("unregister transfer at path %s", this.object_path.to_string ()); + conn.unregister_object (this.register_id); + } + } - public void cancel() { - debug("cancelling job"); - this.transfer.cancel(); - } -} + public void cancel () { + debug ("cancelling job"); + this.transfer.cancel (); + } +} \ No newline at end of file diff --git a/src/mconnect/transfer-upload.vala b/src/mconnect/transfer-upload.vala index 3dbdc24..1cc23c8 100644 --- a/src/mconnect/transfer-upload.vala +++ b/src/mconnect/transfer-upload.vala @@ -18,169 +18,169 @@ class UploadTransfer : TransferInterface, Object { - private FileInputStream finstream = null; - private Cancellable cancellable = null; - private Device device = null; - private TlsConnection tls_conn = null; - private SocketService listener = null; - private uint timeout_source = 0; - private IOCopyJob job = null; - private SocketConnection conn = null; - private uint64 transferred = 0; - private uint64 size; - - private const int WAIT_TIMEOUT = 30; - - public UploadTransfer(Device dev, SocketService listener, - FileInputStream source, uint64 size) { - this.listener = listener; - this.cancellable = new Cancellable(); - this.device = dev; - this.finstream = source; - this.size = size; - } - - public async bool start_async() { - debug("start transfer from to device %s", - this.device.to_string()); - - this.listener.incoming.connect(this.client_connected); - debug("wait for client"); - this.timeout_source = Timeout.add_seconds(WAIT_TIMEOUT, - this.wait_timeout); - this.listener.start(); - - return true; - } - - private bool wait_timeout() { - warning("timeout waiting for client"); - this.listener.stop(); - this.cleanup_error("timeout waiting for client"); - return false; - } - - private bool client_connected(SocketConnection conn, Object? source) { - if (this.timeout_source != 0) { - Source.remove(this.timeout_source); - this.timeout_source = 0; - } - - this.handle_client.begin(conn); - return false; - } - - private async void handle_client(SocketConnection conn) { - var isa = conn.get_remote_address() as InetSocketAddress; - debug("client connected: %s:%u", isa.address.to_string(), - isa.port); - - this.conn = conn; - - var sock = this.conn.get_socket(); - Utils.socket_set_keepalive(sock); - - // enable TLS - this.tls_conn = Utils.make_tls_connection(this.conn, - Core.instance().certificate, - this.device.certificate, - Utils.TlsConnectionMode.SERVER); - try { - debug("attempt TLS handshake"); - var tls_res = yield this.tls_conn.handshake_async(); - debug("TLS handshake complete"); - } catch (Error e) { - var err ="TLS handshake failed: %s".printf(e.message); - warning(err); - this.cleanup_error(err); - return; - } - - this.start_transfer(); - } - - private void start_transfer() { - debug("connected, start transfer"); - this.job = new IOCopyJob(this.finstream, - this.tls_conn.output_stream); - this.job.progress.connect((t, done) => { - int percent = (int) (100.0 * ((double)done / (double)this.size)); - debug("progress: %s/%s %d%%", - format_size(done), format_size(this.size), percent); - this.transferred = done; - }); - - this.started(); - - this.job.start_async.begin(this.cancellable, - this.job_complete); - } - - private void job_complete(Object? obj, AsyncResult res) { - info("transfer finished"); - try { - var rcvd_bytes = this.job.start_async.end(res); - debug("transfer done, got %s", format_size(rcvd_bytes)); - - this.cleanup_success(); - - } catch (Error err) { - warning("transfer failed: %s", err.message); - - this.cleanup_error(err.message); - } - } - - private void cleanup() { - if (this.finstream != null) { - try { - this.finstream.close(); - } catch (IOError e) { - warning("failed to close file input: %s", - e.message); - } - } - - if (this.tls_conn != null) { - try { - this.tls_conn.close(); - } catch (IOError e) { - warning("failed to close TLS connection: %s", - e.message); - } - } - if (this.conn != null) { - try { - this.conn.close(); - } catch (IOError e) { - warning("failed to close connection: %s", - e.message); - } - } - - this.listener.stop(); - this.listener.close(); - this.finstream = null; - this.conn = null; - this.tls_conn = null; - this.job = null; - } - - private void cleanup_error(string reason) { - - this.cleanup(); - - this.error(reason); - } - - private void cleanup_success() { - this.cleanup(); - - this.finished(); - } - - public void cancel() { - debug("cancel called"); - this.cancellable.cancel(); - } + private FileInputStream finstream = null; + private Cancellable cancellable = null; + private Device device = null; + private TlsConnection tls_conn = null; + private SocketService listener = null; + private uint timeout_source = 0; + private IOCopyJob job = null; + private SocketConnection conn = null; + private uint64 transferred = 0; + private uint64 size; + + private const int WAIT_TIMEOUT = 30; + + public UploadTransfer (Device dev, SocketService listener, + FileInputStream source, uint64 size) { + this.listener = listener; + this.cancellable = new Cancellable (); + this.device = dev; + this.finstream = source; + this.size = size; + } + + public async bool start_async () { + debug ("start transfer from to device %s", + this.device.to_string ()); + + this.listener.incoming.connect (this.client_connected); + debug ("wait for client"); + this.timeout_source = Timeout.add_seconds (WAIT_TIMEOUT, + this.wait_timeout); + this.listener.start (); + + return true; + } + + private bool wait_timeout () { + warning ("timeout waiting for client"); + this.listener.stop (); + this.cleanup_error ("timeout waiting for client"); + return false; + } + + private bool client_connected (SocketConnection conn, Object ? source) { + if (this.timeout_source != 0) { + Source.remove (this.timeout_source); + this.timeout_source = 0; + } + + this.handle_client.begin (conn); + return false; + } + + private async void handle_client (SocketConnection conn) { + var isa = conn.get_remote_address () as InetSocketAddress; + debug ("client connected: %s:%u", isa.address.to_string (), + isa.port); + + this.conn = conn; + + var sock = this.conn.get_socket (); + Utils.socket_set_keepalive (sock); + + // enable TLS + this.tls_conn = Utils.make_tls_connection (this.conn, + Core.instance ().certificate, + this.device.certificate, + Utils.TlsConnectionMode.SERVER); + try { + debug ("attempt TLS handshake"); + var tls_res = yield this.tls_conn.handshake_async (); + + debug ("TLS handshake complete"); + } catch (Error e) { + var err = "TLS handshake failed: %s".printf (e.message); + warning (err); + this.cleanup_error (err); + return; + } + + this.start_transfer (); + } + + private void start_transfer () { + debug ("connected, start transfer"); + this.job = new IOCopyJob (this.finstream, + this.tls_conn.output_stream); + this.job.progress.connect ((t, done) => { + int percent = (int) (100.0 * ((double) done / (double) this.size)); + debug ("progress: %s/%s %d%%", + format_size (done), format_size (this.size), percent); + this.transferred = done; + }); + + this.started (); + + this.job.start_async.begin (this.cancellable, + this.job_complete); + } + + private void job_complete (Object ? obj, AsyncResult res) { + info ("transfer finished"); + try { + var rcvd_bytes = this.job.start_async.end (res); + debug ("transfer done, got %s", format_size (rcvd_bytes)); + + this.cleanup_success (); + } catch (Error err) { + warning ("transfer failed: %s", err.message); + + this.cleanup_error (err.message); + } + } + + private void cleanup () { + if (this.finstream != null) { + try { + this.finstream.close (); + } catch (IOError e) { + warning ("failed to close file input: %s", + e.message); + } + } + + if (this.tls_conn != null) { + try { + this.tls_conn.close (); + } catch (IOError e) { + warning ("failed to close TLS connection: %s", + e.message); + } + } + if (this.conn != null) { + try { + this.conn.close (); + } catch (IOError e) { + warning ("failed to close connection: %s", + e.message); + } + } + + this.listener.stop (); + this.listener.close (); + this.finstream = null; + this.conn = null; + this.tls_conn = null; + this.job = null; + } + + private void cleanup_error (string reason) { + + this.cleanup (); + + this.error (reason); + } + + private void cleanup_success () { + this.cleanup (); + + this.finished (); + } + + public void cancel () { + debug ("cancel called"); + this.cancellable.cancel (); + } } \ No newline at end of file diff --git a/src/mconnect/utils.vala b/src/mconnect/utils.vala index 69512b8..ec4bea9 100644 --- a/src/mconnect/utils.vala +++ b/src/mconnect/utils.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,182 +18,184 @@ namespace Utils { -using Posix; - - /** - * make_unique_device_string: - * @id: device ID - * @name: device name - * @type: device type - * @pv: protocol version - * - * Generate device string that can be used as map index - */ - string make_unique_device_string(string id, string name, - string type, uint pv) { - return make_device_string(id, name, type, pv).replace(" ", "-"); - } - - /** - * make_device_string: - * @id: device ID - * @name: device name - * @type: device type - * @pv: protocol version - * - * Generate device string - */ - string make_device_string(string id, string name, - string type, uint pv) { - return "%s-%s-%s-%u".printf(id, name, type, pv); - - } - - /** - * socket_set_keepalive: - * @sock: socket - * - * Set keepalive counters on socket - */ - void socket_set_keepalive(Socket sock) { + using Posix; + + /** + * make_unique_device_string: + * @id: device ID + * @name: device name + * @type: device type + * @pv: protocol version + * + * Generate device string that can be used as map index + */ + string make_unique_device_string (string id, string name, + string type, uint pv) { + return make_device_string (id, name, type, pv).replace (" ", "-"); + } + + /** + * make_device_string: + * @id: device ID + * @name: device name + * @type: device type + * @pv: protocol version + * + * Generate device string + */ + string make_device_string (string id, string name, + string type, uint pv) { + return "%s-%s-%s-%u".printf (id, name, type, pv); + } + + /** + * socket_set_keepalive: + * @sock: socket + * + * Set keepalive counters on socket + */ + void socket_set_keepalive (Socket sock) { #if 0 - IPPROTO_TCP = 6, /* Transmission Control Protocol. */ + IPPROTO_TCP = 6, /* Transmission Control Protocol. */ - TCP_KEEPIDLE 4 /* Start keeplives after this period */ - TCP_KEEPINTVL 5 /* Interval between keepalives */ - TCP_KEEPCNT 6 /* Number of keepalives before death */ + TCP_KEEPIDLE 4 /* Start keeplives after this period */ + TCP_KEEPINTVL 5 /* Interval between keepalives */ + TCP_KEEPCNT 6 /* Number of keepalives before death */ #endif #if 0 - int option = 10; - Posix.setsockopt(sock.fd, 6, 4, &option, (Posix.socklen_t) sizeof(int)); - option = 5; - Posix.setsockopt(sock.fd, 6, 5, &option, (Posix.socklen_t) sizeof(int)); - option = 3; - Posix.setsockopt(sock.fd, 6, 6, &option, (Posix.socklen_t) sizeof(int)); + int option = 10; + Posix.setsockopt (sock.fd, 6, 4, &option, (Posix.socklen_t) sizeof (int)); + option = 5; + Posix.setsockopt (sock.fd, 6, 5, &option, (Posix.socklen_t) sizeof (int)); + option = 3; + Posix.setsockopt (sock.fd, 6, 6, &option, (Posix.socklen_t) sizeof (int)); #endif - int option = 10; - Posix.setsockopt(sock.fd, IPProto.TCP, - Posix.TCP_KEEPIDLE, - &option, (Posix.socklen_t) sizeof(int)); - option = 5; - Posix.setsockopt(sock.fd, IPProto.TCP, - Posix.TCP_KEEPINTVL, - &option, (Posix.socklen_t) sizeof(int)); - option = 3; - Posix.setsockopt(sock.fd, IPProto.TCP, - Posix.TCP_KEEPCNT, - &option, (Posix.socklen_t) sizeof(int)); - - // enable keepalive - sock.set_keepalive(true); - } - - public enum TlsConnectionMode { - SERVER, - CLIENT, - } - /** - * make_tls_connection: - * - * Create a TLS connection around given connected socket. - * When @expected_peer is non-null, the handshake will be rejected if the - * certificate presented by peer is different from expected. - * - * @sock_conn: connected socket - * @self_cert: own certificate - * @expected_peer: expected peer certificate - * @is_client_connection: if true then TLS client side connection is prepared - * - * @return new TlsConnection - */ - TlsConnection make_tls_connection(SocketConnection sock_conn, - TlsCertificate self_cert, - TlsCertificate? expected_peer = null, - TlsConnectionMode mode = TlsConnectionMode.SERVER) { - TlsConnection tls_conn; - - if (mode == TlsConnectionMode.SERVER) { - debug("creating TLS server connection"); - var tls_serv = TlsServerConnection.@new(sock_conn, self_cert); - tls_serv.authentication_mode = TlsAuthenticationMode.REQUESTED; - tls_conn = tls_serv; - } else { - debug("creating TLS client connection"); - tls_conn = TlsClientConnection.@new(sock_conn, - sock_conn.get_remote_address()); - tls_conn.set_certificate(self_cert); - } - tls_conn.accept_certificate.connect((peer_cert, errors) => { - info("accept certificate, flags: 0x%x", errors); - info("certificate:\n%s\n", peer_cert.certificate_pem); - - if (expected_peer != null) { - if (Logging.VERBOSE) { - vdebug("verify certificate, expecting: %s, got: %s", - expected_peer.certificate_pem, - peer_cert.certificate_pem); - } - - if (expected_peer.is_same(peer_cert)) { - return true; - } else { - warning("rejecting handshare, peer certificate mismatch, got:\n%s", - peer_cert.certificate_pem); - return false; - } - } - return true; - }); - return tls_conn; - } - - /** - * find_urls: - * - * Locate and extract URL like patterns in the text. URLs are assumed to - * start with http or https. - * - * @text: input test - * @return array of matches, if there were none then array if of length 0 - */ - string[] find_urls(string text) { - try { - // regex taken from SO + int option = 10; + Posix.setsockopt (sock.fd, IPProto.TCP, + Posix.TCP_KEEPIDLE, + &option, (Posix.socklen_t) sizeof (int)); + option = 5; + Posix.setsockopt (sock.fd, IPProto.TCP, + Posix.TCP_KEEPINTVL, + &option, (Posix.socklen_t) sizeof (int)); + option = 3; + Posix.setsockopt (sock.fd, IPProto.TCP, + Posix.TCP_KEEPCNT, + &option, (Posix.socklen_t) sizeof (int)); + + // enable keepalive + sock.set_keepalive (true); + } + + public enum TlsConnectionMode { + SERVER, + CLIENT, + } + /** + * make_tls_connection: + * + * Create a TLS connection around given connected socket. + * When @expected_peer is non-null, the handshake will be rejected if the + * certificate presented by peer is different from expected. + * + * @sock_conn: connected socket + * @self_cert: own certificate + * @expected_peer: expected peer certificate + * @is_client_connection: if true then TLS client side connection is prepared + * + * @return new TlsConnection + */ + TlsConnection make_tls_connection (SocketConnection sock_conn, + TlsCertificate self_cert, + TlsCertificate ? expected_peer = null, + TlsConnectionMode mode = TlsConnectionMode.SERVER) { + TlsConnection tls_conn; + + if (mode == TlsConnectionMode.SERVER) { + debug ("creating TLS server connection"); + var tls_serv = TlsServerConnection.@new (sock_conn, self_cert); + tls_serv.authentication_mode = TlsAuthenticationMode.REQUESTED; + tls_conn = tls_serv; + } else { + debug ("creating TLS client connection"); + tls_conn = TlsClientConnection.@new (sock_conn, + sock_conn.get_remote_address ()); + tls_conn.set_certificate (self_cert); + } + tls_conn.accept_certificate.connect ((peer_cert, errors) => { + info ("accept certificate, flags: 0x%x", errors); + info ("certificate:\n%s\n", peer_cert.certificate_pem); + + if (expected_peer != null) { + if (Logging.VERBOSE) { + vdebug ("verify certificate, expecting: %s, got: %s", + expected_peer.certificate_pem, + peer_cert.certificate_pem); + } + + if (expected_peer.is_same (peer_cert)) { + return true; + } else { + warning ("rejecting handshare, peer certificate mismatch, got:\n%s", + peer_cert.certificate_pem); + return false; + } + } + return true; + }); + return tls_conn; + } + + /** + * find_urls: + * + * Locate and extract URL like patterns in the text. URLs are assumed to + * start with http or https. + * + * @text: input test + * @return array of matches, if there were none then array if of length 0 + */ + string[] find_urls (string text) { + try { + + // regex taken from SO + // uncrustify breaks the regex, so *INDENT-OFF* Regex r = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+,.~#?&\/=]*)/; - - MatchInfo mi; - - string[] matches = {}; - - if (r.match(text, RegexMatchFlags.NOTEMPTY, out mi)) { - while (mi.matches()) { - if (mi.is_partial_match() == false) { - var m = mi.fetch(0); - debug("found match %s", m); - matches += m; - } - mi.next(); - } - } else { - debug("no match"); - } - return matches; - } catch (RegexError e) { - warning("failed to compile regex: %s", e.message); - return null; - } - } - - public void show_own_notification(string message, - string summary = "mconnect", - string icon = "dialog-information") { - try { - var notif = new Notify.Notification(summary, message, - "phone"); - notif.show(); - } catch (Error e) { - critical("failed to show notification: %s", e.message); - } - } + // *INDENT-ON* + + MatchInfo mi; + + string[] matches = {}; + + if (r.match (text, RegexMatchFlags.NOTEMPTY, out mi)) { + while (mi.matches ()) { + if (mi.is_partial_match () == false) { + var m = mi.fetch (0); + debug ("found match %s", m); + matches += m; + } + mi.next (); + } + } else { + debug ("no match"); + } + return matches; + } catch (RegexError e) { + warning ("failed to compile regex: %s", e.message); + return null; + } + } + + public void show_own_notification (string message, + string summary = "mconnect", + string icon = "dialog-information") { + try { + var notif = new Notify.Notification (summary, message, + "phone"); + notif.show (); + } catch (Error e) { + critical ("failed to show notification: %s", e.message); + } + } } \ No newline at end of file diff --git a/src/mconnectctl/device-iface.vala b/src/mconnectctl/device-iface.vala index c3bc3ac..6e02321 100644 --- a/src/mconnectctl/device-iface.vala +++ b/src/mconnectctl/device-iface.vala @@ -17,21 +17,44 @@ */ namespace Mconnect { - [DBus (name = "org.mconnect.Device")] - public interface DeviceIface : Object { - - public abstract string id { owned get;} - public abstract string name { owned get;} - public abstract string device_type { owned get;} - public abstract uint protocol_version { owned get;} - public abstract string address { owned get;} - public abstract bool is_paired { owned get;} - public abstract bool allowed { owned get;} - public abstract bool is_active { owned get;} - public abstract bool is_connected { owned get;} - public abstract string[] outgoing_capabilities { owned get;} - public abstract string[] incoming_capabilities { owned get;} - public abstract string certificate { owned get;} - } + [DBus (name = "org.mconnect.Device")] + public interface DeviceIface : Object { + public abstract string id { + owned get; + } + public abstract string name { + owned get; + } + public abstract string device_type { + owned get; + } + public abstract uint protocol_version { + owned get; + } + public abstract string address { + owned get; + } + public abstract bool is_paired { + owned get; + } + public abstract bool allowed { + owned get; + } + public abstract bool is_active { + owned get; + } + public abstract bool is_connected { + owned get; + } + public abstract string[] outgoing_capabilities { + owned get; + } + public abstract string[] incoming_capabilities { + owned get; + } + public abstract string certificate { + owned get; + } + } } \ No newline at end of file diff --git a/src/mconnectctl/device-manager-iface.vala b/src/mconnectctl/device-manager-iface.vala index 6ae2d47..0cf9d04 100644 --- a/src/mconnectctl/device-manager-iface.vala +++ b/src/mconnectctl/device-manager-iface.vala @@ -17,12 +17,12 @@ */ namespace Mconnect { - [DBus (name = "org.mconnect.DeviceManager")] - public interface DeviceManagerIface : Object { + [DBus (name = "org.mconnect.DeviceManager")] + public interface DeviceManagerIface : Object { - public const string OBJECT_PATH = "/org/mconnect/manager"; + public const string OBJECT_PATH = "/org/mconnect/manager"; - public abstract ObjectPath[] ListDevices() throws IOError; - public abstract void AllowDevice(string path) throws IOError; - } + public abstract ObjectPath[] ListDevices () throws IOError; + public abstract void AllowDevice (string path) throws IOError; + } } \ No newline at end of file diff --git a/src/mconnectctl/main.vala b/src/mconnectctl/main.vala index 4c24c70..852613a 100644 --- a/src/mconnectctl/main.vala +++ b/src/mconnectctl/main.vala @@ -20,53 +20,51 @@ namespace Mconnect { - public class Client { - - private static bool log_debug = false; - private static bool verbose = false; - // some hints for valac about the array holding remaining args - [CCode (array_length = false, array_null_terminated = true)] - private static string[] remaining; - private BusType bus_type = BusType.SESSION; - - private const OptionEntry[] options = { - {"debug", 'd', 0, OptionArg.NONE, ref log_debug, - "Show debug output", null}, - {"verbose", 'v', 0, OptionArg.NONE, ref verbose, - "Be verbose", null}, - // there's no Vala const for G_OPTION_REMAINING (which is a #define - // for "") - {"", 0, 0, OptionArg.STRING_ARRAY, ref remaining, null, - "[COMMAND ..]"}, - {null} - }; - - /** - * Command: - * - * command line 'command' wrapper - */ - private struct Command { - string command; // textual command, ex. list, show, etc. - int arg_count; // number of required parameters, not including - // command - unowned CommandFunc clbk; // callback - - Command(string command, int arg_count, CommandFunc clbk) { - this.command = command; - this.arg_count = arg_count; - this.clbk = clbk; - } - } - // command callback - private delegate int CommandFunc(string[] args); - - public static int main(string[] args) - { - try { - var opt_context = new OptionContext(); - opt_context.set_description( - """Available commands: + public class Client { + + private static bool log_debug = false; + private static bool verbose = false; + // some hints for valac about the array holding remaining args + [CCode (array_length = false, array_null_terminated = true)] + private static string[] remaining; + private BusType bus_type = BusType.SESSION; + + private const OptionEntry[] options = { + { "debug", 'd', 0, OptionArg.NONE, ref log_debug, + "Show debug output", null }, + { "verbose", 'v', 0, OptionArg.NONE, ref verbose, + "Be verbose", null }, + // there's no Vala const for G_OPTION_REMAINING (which is a #define + // for "") + { "", 0, 0, OptionArg.STRING_ARRAY, ref remaining, null, + "[COMMAND ..]" }, + { null } + }; + + /** + * Command: + * + * command line 'command' wrapper + */ + private struct Command { + string command; // textual command, ex. list, show, etc. + int arg_count; // number of required parameters, not including command + unowned CommandFunc clbk; // callback + + Command (string command, int arg_count, CommandFunc clbk) { + this.command = command; + this.arg_count = arg_count; + this.clbk = clbk; + } + } + // command callback + private delegate int CommandFunc (string[] args); + + public static int main (string[] args) { + try { + var opt_context = new OptionContext (); + opt_context.set_description ( + """Available commands: list-devices List devices allow-device Allow device show-device Show device details @@ -77,308 +75,309 @@ namespace Mconnect { send-sms Send SMS """ - ); - opt_context.set_help_enabled(true); - opt_context.add_main_entries(options, null); - opt_context.parse(ref args); - } catch (OptionError e) { - stdout.printf("error: %s\n", e.message); - stdout.printf("Run '%s --help' to see a full " + - "list of available command line options.\n", - args[0]); - return 1; - } - - if (log_debug == true) - Environment.set_variable("G_MESSAGES_DEBUG", "all", false); - - var cl = new Client(); - - Command[] commands = { - Command("list-devices", 0, cl.cmd_list_devices), - Command("allow-device", 1, cl.cmd_allow_device), - Command("show-device", 1, cl.cmd_show_device), - Command("share-url", 2, cl.cmd_share_url), - Command("share-text", 2, cl.cmd_share_text), - Command("share-file", 2, cl.cmd_share_file), - Command("send-sms", 3, cl.cmd_send_sms), - }; - handle_command(remaining, commands); - - return 0; - } - - /** - * handle_command: - * @args: remaining command line arguments - * @commands: supported commands array - * - * @return exit status of command or -1 on error - */ - private static int handle_command(string[] args, Command[] commands) { - // extract command and it's arguments if any - string command = "list-devices"; - - if (args.length > 0) - command = remaining[0]; - debug("command is: %s", command); - - string[] command_args = {}; - if (args.length > 1) - command_args = args[1:args.length]; - - foreach (var cmden in commands) { - if (cmden.command == command) { - debug("found match for %s, args expect: %zd, have: %zd", - command, cmden.arg_count, command_args.length); - - if (command_args.length != cmden.arg_count) { - stderr.printf("Incorrect number of arguments " + - "for command %s, see --help\n", - command); - return -1; - } - - debug("running callback"); - return cmden.clbk(command_args); - } - } - - stderr.printf("Incorrect command, see --help\n"); - return -1; - } - - private int cmd_list_devices(string[] args) { - return checked_dbus_call(() => { - var manager = get_manager(); - debug("list devices"); - var devs = manager.ListDevices(); - print_paths(devs, "Devices", - (path) => { - try { - var dp = get_device(path); - return "%s - %s".printf(dp.id, dp.name); - } catch (IOError e) { - warning("error occurred: %s", e.message); - return "(error)"; - } - }); - return 0; - }); - } - - private int cmd_allow_device(string[] args) { - return checked_dbus_call(() => { - var dp = args[0]; - var manager = get_manager(); - debug("allow device device %s", dp); - manager.AllowDevice(new ObjectPath(dp)); - return 0; - }); - } - - private int cmd_share_url(string[] args) { - return checked_dbus_call(() => { - var dp = args[0]; - var share = get_share(new ObjectPath(dp)); - share.share_url(args[1]); - return 0; - }); - } - - private int cmd_share_text(string[] args) { - return checked_dbus_call(() => { - var dp = args[0]; - var share = get_share(new ObjectPath(dp)); - share.share_text(args[1]); - return 0; - }); - } - - private int cmd_share_file(string[] args) { - return checked_dbus_call(() => { - var dp = args[0]; - var share = get_share(new ObjectPath(dp)); - var file = File.new_for_path(args[1]); - var path = file.get_path(); - debug("share path: %s", path); - share.share_file(path); - return 0; - }); - } - - private int cmd_send_sms(string[] args) { - return checked_dbus_call(() => { - var dp = args[0]; - var number = args[1]; - var message = args[2]; - var telephony = get_telephony(new ObjectPath(dp)); - telephony.send_sms(number, message); - return 0; - }); - } - - private void print_sorted_caps(string[] caps, string format) { - qsort_with_data(caps, sizeof(string), - (a, b) => GLib.strcmp(a, b)); - foreach (var cap in caps) { - stdout.printf(format, cap); - } - } - - private int cmd_show_device(string[] args) { - return checked_dbus_call(() => { - var dp = get_device(new ObjectPath(args[0])); - - stdout.printf("Device\n" + - " Name: %s\n" + - " ID: %s\n" + - " Address: %s\n" + - " Type: %s\n" + - " Allowed: %s\n" + - " Paired: %s\n" + - " Active: %s\n" + - " Connected: %s\n", - dp.name, - dp.id, - dp.address, - dp.device_type, - dp.allowed.to_string(), - dp.is_paired.to_string(), - dp.is_active.to_string(), - dp.is_connected.to_string()); - if (verbose) { - stdout.printf(" Capabilities (out):\n"); - print_sorted_caps(dp.outgoing_capabilities, " %s\n"); - stdout.printf(" Capabilities (in):\n"); - print_sorted_caps(dp.incoming_capabilities, " %s\n"); - stdout.printf(" Certificate:\n%s\n", dp.certificate); - } - return 0; - }); - } - - private delegate int CheckDBusCallFunc() throws Error; - /** - * checked_dbus_call: - * @clbk: function to wrap - * - * Catch any DBus errors and return appropriate status - */ - private static int checked_dbus_call(CheckDBusCallFunc clbk) { - try { - return clbk(); - } catch (IOError e) { - warning("communication returned an error: %s", e.message); - return -1; - } catch (DBusError e) { - warning("communication with service failed: %s", e.message); - } catch (Error e) { - warning("error: %s", e.message); - } - return 0; - } - - /** - * get_mconnect_obj_proxy: - * @path: DBus object path - * - * Obtain an interface to a DBus object avaialble at - * Mconnect service under @path. - * - * @return null or interface - */ - private T? get_mconnect_obj_proxy(ObjectPath path) throws IOError { - T proxy_out = null; - try { - proxy_out = Bus.get_proxy_sync(bus_type, - "org.mconnect", - path); - } catch (IOError e) { - warning("failed to obtain proxy to mconnect service: %s", - e.message); - throw e; - } - return proxy_out; - } - - /** - * get_manager: - * - * Obtain DBus interface to Device Manager - * - * @return interface or null - */ - private DeviceManagerIface? get_manager() throws IOError { - return get_mconnect_obj_proxy( - new ObjectPath(DeviceManagerIface.OBJECT_PATH)); - } - - /** - * get_device: - * @path device object path - * - * Obtain DBus interface to Device - * - * @return interface or null - */ - private DeviceIface? get_device(ObjectPath path) throws IOError { - return get_mconnect_obj_proxy(path); - } - - /** - * get_share: - * - * Obtain DBus interface to Share of given device - * - * @return interface or null - */ - private ShareIface? get_share(ObjectPath path) throws IOError { - return get_mconnect_obj_proxy(path); - } - - /** - * get_telephony: - * - * Obtain DBus interface to Telephony of given device - * - * @return interface or null - */ - private TelephonyIface? get_telephony(ObjectPath path) throws IOError { - return get_mconnect_obj_proxy(path); - } - - /** - * print_paths: - * @objs: object paths - * @header: header for printing, - * @desc_clbk: callback for producing a meaningful description - * - * Print a list of object paths, possibly adding a description - */ - private static void print_paths(ObjectPath[] objs, string header, - GetDescFunc desc_clbk) { - if (objs.length == 0) - stdout.printf("No objects were found\n"); - else { - stdout.printf(header + ":\n"); - foreach (var o in objs) { - string desc = null; - - if (desc_clbk != null) { - debug("calling description callback for obj: %s", - o.to_string()); - desc = desc_clbk(o); - } - - stdout.printf(" %s", o.to_string()); - if (desc != null) - stdout.printf(" %s", desc); - stdout.printf("\n"); - } - } - } - - private delegate string GetDescFunc(ObjectPath obj_path); - } -} + ); + opt_context.set_help_enabled (true); + opt_context.add_main_entries (options, null); + opt_context.parse (ref args); + } catch (OptionError e) { + stdout.printf ("error: %s\n", e.message); + stdout.printf ("Run '%s --help' to see a full " + + "list of available command line options.\n", + args[0]); + return 1; + } + + if (log_debug == true) + Environment.set_variable ("G_MESSAGES_DEBUG", "all", false); + + var cl = new Client (); + + Command[] commands = { + Command ("list-devices", 0, cl.cmd_list_devices), + Command ("allow-device", 1, cl.cmd_allow_device), + Command ("show-device", 1, cl.cmd_show_device), + Command ("share-url", 2, cl.cmd_share_url), + Command ("share-text", 2, cl.cmd_share_text), + Command ("share-file", 2, cl.cmd_share_file), + Command ("send-sms", 3, cl.cmd_send_sms), + }; + handle_command (remaining, commands); + + return 0; + } + + /** + * handle_command: + * @args: remaining command line arguments + * @commands: supported commands array + * + * @return exit status of command or -1 on error + */ + private static int handle_command (string[] args, Command[] commands) { + // extract command and it's arguments if any + string command = "list-devices"; + + if (args.length > 0) + command = remaining[0]; + debug ("command is: %s", command); + + string[] command_args = {}; + if (args.length > 1) + command_args = args[1 : args.length]; + + foreach (var cmden in commands) { + if (cmden.command == command) { + debug ("found match for %s, args expect: %zd, have: %zd", + command, cmden.arg_count, command_args.length); + + if (command_args.length != cmden.arg_count) { + stderr.printf ("Incorrect number of arguments " + + "for command %s, see --help\n", + command); + return -1; + } + + debug ("running callback"); + return cmden.clbk (command_args); + } + } + + stderr.printf ("Incorrect command, see --help\n"); + return -1; + } + + private int cmd_list_devices (string[] args) { + return checked_dbus_call (() => { + var manager = get_manager (); + debug ("list devices"); + var devs = manager.ListDevices (); + print_paths (devs, "Devices", + (path) => { + try { + var dp = get_device (path); + return "%s - %s".printf (dp.id, dp.name); + } catch (IOError e) { + warning ("error occurred: %s", e.message); + return "(error)"; + } + }); + return 0; + }); + } + + private int cmd_allow_device (string[] args) { + return checked_dbus_call (() => { + var dp = args[0]; + var manager = get_manager (); + debug ("allow device device %s", dp); + manager.AllowDevice (new ObjectPath (dp)); + return 0; + }); + } + + private int cmd_share_url (string[] args) { + return checked_dbus_call (() => { + var dp = args[0]; + var share = get_share (new ObjectPath (dp)); + share.share_url (args[1]); + return 0; + }); + } + + private int cmd_share_text (string[] args) { + return checked_dbus_call (() => { + var dp = args[0]; + var share = get_share (new ObjectPath (dp)); + share.share_text (args[1]); + return 0; + }); + } + + private int cmd_share_file (string[] args) { + return checked_dbus_call (() => { + var dp = args[0]; + var share = get_share (new ObjectPath (dp)); + var file = File.new_for_path (args[1]); + var path = file.get_path (); + debug ("share path: %s", path); + share.share_file (path); + return 0; + }); + } + + private int cmd_send_sms (string[] args) { + return checked_dbus_call (() => { + var dp = args[0]; + var number = args[1]; + var message = args[2]; + var telephony = get_telephony (new ObjectPath (dp)); + telephony.send_sms (number, message); + return 0; + }); + } + + private void print_sorted_caps (string[] caps, string format) { + qsort_with_data(caps, sizeof (string), + (a, b) => GLib.strcmp (a, b)); + foreach (var cap in caps) { + stdout.printf (format, cap); + } + } + + private int cmd_show_device (string[] args) { + return checked_dbus_call (() => { + var dp = get_device (new ObjectPath (args[0])); + + stdout.printf ("Device\n" + + " Name: %s\n" + + " ID: %s\n" + + " Address: %s\n" + + " Type: %s\n" + + " Allowed: %s\n" + + " Paired: %s\n" + + " Active: %s\n" + + " Connected: %s\n", + dp.name, + dp.id, + dp.address, + dp.device_type, + dp.allowed.to_string (), + dp.is_paired.to_string (), + dp.is_active.to_string (), + dp.is_connected.to_string ()); + if (verbose) { + stdout.printf (" Capabilities (out):\n"); + print_sorted_caps (dp.outgoing_capabilities, " %s\n"); + stdout.printf (" Capabilities (in):\n"); + print_sorted_caps (dp.incoming_capabilities, " %s\n"); + stdout.printf (" Certificate:\n%s\n", dp.certificate); + } + return 0; + }); + } + + private delegate int CheckDBusCallFunc () throws Error; + + /** + * checked_dbus_call: + * @clbk: function to wrap + * + * Catch any DBus errors and return appropriate status + */ + private static int checked_dbus_call (CheckDBusCallFunc clbk) { + try { + return clbk (); + } catch (IOError e) { + warning ("communication returned an error: %s", e.message); + return -1; + } catch (DBusError e) { + warning ("communication with service failed: %s", e.message); + } catch (Error e) { + warning ("error: %s", e.message); + } + return 0; + } + + /** + * get_mconnect_obj_proxy: + * @path: DBus object path + * + * Obtain an interface to a DBus object avaialble at + * Mconnect service under @path. + * + * @return null or interface + */ + private T ? get_mconnect_obj_proxy(ObjectPath path) throws IOError { + T proxy_out = null; + try { + proxy_out = Bus.get_proxy_sync (bus_type, + "org.mconnect", + path); + } catch (IOError e) { + warning ("failed to obtain proxy to mconnect service: %s", + e.message); + throw e; + } + return proxy_out; + } + + /** + * get_manager: + * + * Obtain DBus interface to Device Manager + * + * @return interface or null + */ + private DeviceManagerIface ? get_manager () throws IOError { + return get_mconnect_obj_proxy ( + new ObjectPath (DeviceManagerIface.OBJECT_PATH)); + } + + /** + * get_device: + * @path device object path + * + * Obtain DBus interface to Device + * + * @return interface or null + */ + private DeviceIface ? get_device (ObjectPath path) throws IOError { + return get_mconnect_obj_proxy (path); + } + + /** + * get_share: + * + * Obtain DBus interface to Share of given device + * + * @return interface or null + */ + private ShareIface ? get_share (ObjectPath path) throws IOError { + return get_mconnect_obj_proxy (path); + } + + /** + * get_telephony: + * + * Obtain DBus interface to Telephony of given device + * + * @return interface or null + */ + private TelephonyIface ? get_telephony (ObjectPath path) throws IOError { + return get_mconnect_obj_proxy (path); + } + + /** + * print_paths: + * @objs: object paths + * @header: header for printing, + * @desc_clbk: callback for producing a meaningful description + * + * Print a list of object paths, possibly adding a description + */ + private static void print_paths (ObjectPath[] objs, string header, + GetDescFunc desc_clbk) { + if (objs.length == 0) + stdout.printf ("No objects were found\n"); + else { + stdout.printf (header + ":\n"); + foreach (var o in objs) { + string desc = null; + + if (desc_clbk != null) { + debug ("calling description callback for obj: %s", + o.to_string ()); + desc = desc_clbk (o); + } + + stdout.printf (" %s", o.to_string ()); + if (desc != null) + stdout.printf (" %s", desc); + stdout.printf ("\n"); + } + } + } + + private delegate string GetDescFunc (ObjectPath obj_path); + } +} \ No newline at end of file diff --git a/src/mconnectctl/share-iface.vala b/src/mconnectctl/share-iface.vala index 611111f..59aaf07 100644 --- a/src/mconnectctl/share-iface.vala +++ b/src/mconnectctl/share-iface.vala @@ -18,12 +18,11 @@ namespace Mconnect { - [DBus (name = "org.mconnect.Device.Share")] - public interface ShareIface : Object { - - public abstract void share_url(string url) throws IOError; - public abstract void share_text(string text) throws IOError; - public abstract void share_file(string path) throws IOError; - } + [DBus (name = "org.mconnect.Device.Share")] + public interface ShareIface : Object { + public abstract void share_url (string url) throws IOError; + public abstract void share_text (string text) throws IOError; + public abstract void share_file (string path) throws IOError; + } } \ No newline at end of file diff --git a/src/mconnectctl/telephony-iface.vala b/src/mconnectctl/telephony-iface.vala index 680b6ce..1b20705 100644 --- a/src/mconnectctl/telephony-iface.vala +++ b/src/mconnectctl/telephony-iface.vala @@ -18,11 +18,10 @@ namespace Mconnect { - [DBus (name = "org.mconnect.Device.Telephony")] - public interface TelephonyIface : Object { - - public abstract void send_sms(string number, - string message) throws IOError; - } + [DBus (name = "org.mconnect.Device.Telephony")] + public interface TelephonyIface : Object { + public abstract void send_sms (string number, + string message) throws IOError; + } } \ No newline at end of file diff --git a/test/mconn-crypt-vala-test.vala b/test/mconn-crypt-vala-test.vala index 311d4b9..8cf9b7b 100644 --- a/test/mconn-crypt-vala-test.vala +++ b/test/mconn-crypt-vala-test.vala @@ -1,93 +1,95 @@ using Mconn; -void test_generate() { - string key_path = "/tmp/test-key-vala.pem"; - string cert_path = "/tmp/test-cert-vala.pem"; - FileUtils.remove(key_path); - FileUtils.remove(cert_path); - - assert(FileUtils.test(key_path, FileTest.EXISTS) == false); - try { - Crypt.generate_key_cert(key_path, cert_path, "foo"); - } catch (Error e) { - warning("generate failed: %s", e.message); - Test.fail(); - } - assert(FileUtils.test(key_path, FileTest.EXISTS) == true); - assert(FileUtils.test(cert_path, FileTest.EXISTS) == true); +void test_generate () { + string key_path = "/tmp/test-key-vala.pem"; + string cert_path = "/tmp/test-cert-vala.pem"; + FileUtils.remove (key_path); + FileUtils.remove (cert_path); + + assert (FileUtils.test (key_path, FileTest.EXISTS) == false); + try { + Crypt.generate_key_cert (key_path, cert_path, "foo"); + } catch (Error e) { + warning ("generate failed: %s", e.message); + Test.fail (); + } + assert (FileUtils.test (key_path, FileTest.EXISTS) == true); + assert (FileUtils.test (cert_path, FileTest.EXISTS) == true); } -void test_generate_load() { - string key_path = "/tmp/test-key-vala.pem"; - string cert_path = "/tmp/test-cert-vala.pem"; - FileUtils.remove(key_path); - FileUtils.remove(cert_path); - - try { - Crypt.generate_key_cert(key_path, cert_path, "bar"); - } catch (Error e) { - warning("generate failed: %s", e.message); - Test.fail(); - } - - try { - var cert = new TlsCertificate.from_files(cert_path, - key_path); - } catch (Error e) { - warning("load from files failed: %s", e.message); - Test.fail(); - } +void test_generate_load () { + string key_path = "/tmp/test-key-vala.pem"; + string cert_path = "/tmp/test-cert-vala.pem"; + FileUtils.remove (key_path); + FileUtils.remove (cert_path); + + try { + Crypt.generate_key_cert (key_path, cert_path, "bar"); + } catch (Error e) { + warning ("generate failed: %s", e.message); + Test.fail (); + } + + try { + var cert = new TlsCertificate.from_files (cert_path, + key_path); + } catch (Error e) { + warning ("load from files failed: %s", e.message); + Test.fail (); + } } -void test_custom_cn() { - string key_path = "/tmp/test-key-vala.pem"; - string cert_path = "/tmp/test-cert-vala.pem"; - FileUtils.remove(key_path); - FileUtils.remove(cert_path); - - try { - Crypt.generate_key_cert(key_path, cert_path, "custom-cn"); - } catch (Error e) { - warning("generate failed: %s", e.message); - Test.fail(); - } - - uint8[] data; - try { - File.new_for_path(cert_path).load_contents(null, out data, null); - } catch (Error e) { - warning("load contents failed: %s", e.message); - Test.fail(); - } - - var datum = GnuTLS.Datum() { data=data, size=data.length }; - - var cert = GnuTLS.X509.Certificate.create(); - var res = cert.import(ref datum, GnuTLS.X509.CertificateFormat.PEM); - assert(res == GnuTLS.ErrorCode.SUCCESS); - - // verify DN - var dn = new uint8[1024]; - size_t sz = dn.length; - cert.get_dn(dn, ref sz); - debug("dn: %s\n", (string)dn); - - var issuer_dn = new uint8[1024]; - sz = issuer_dn.length; - cert.get_issuer_dn(issuer_dn, ref sz); - debug("dn: %s\n", (string)issuer_dn); - - var subject = (string)dn; - var issuer = (string)issuer_dn; - - // verify that the certificate is self signed - assert(subject == issuer); - // - assert("CN=custom-cn" in subject); +void test_custom_cn () { + string key_path = "/tmp/test-key-vala.pem"; + string cert_path = "/tmp/test-cert-vala.pem"; + FileUtils.remove (key_path); + FileUtils.remove (cert_path); + + try { + Crypt.generate_key_cert (key_path, cert_path, "custom-cn"); + } catch (Error e) { + warning ("generate failed: %s", e.message); + Test.fail (); + } + + uint8[] data; + try { + File.new_for_path (cert_path).load_contents (null, out data, null); + } catch (Error e) { + warning ("load contents failed: %s", e.message); + Test.fail (); + } + + var datum = GnuTLS.Datum () { + data = data, size = data.length + }; + + var cert = GnuTLS.X509.Certificate.create (); + var res = cert.import (ref datum, GnuTLS.X509.CertificateFormat.PEM); + assert (res == GnuTLS.ErrorCode.SUCCESS); + + // verify DN + var dn = new uint8[1024]; + size_t sz = dn.length; + cert.get_dn (dn, ref sz); + debug ("dn: %s\n", (string) dn); + + var issuer_dn = new uint8[1024]; + sz = issuer_dn.length; + cert.get_issuer_dn (issuer_dn, ref sz); + debug ("dn: %s\n", (string) issuer_dn); + + var subject = (string) dn; + var issuer = (string) issuer_dn; + + // verify that the certificate is self signed + assert (subject == issuer); + // + assert ("CN=custom-cn" in subject); } -void test_fingerprint() { - var pem = """-----BEGIN CERTIFICATE----- +void test_fingerprint () { + var pem = """-----BEGIN CERTIFICATE----- MIIC8jCCAdoCAQowDQYJKoZIhvcNAQEFBQAwPzERMA8GA1UEChMIbWNvbm5lY3Qx ETAPBgNVBAsTCG1jb25uZWN0MRcwFQYDVQQDDA5tYWNpZWtAY29yc2FpcjAeFw0x NzA5MjQxOTU3NDVaFw0yNzA5MjQxOTU3NDVaMD8xETAPBgNVBAoTCG1jb25uZWN0 @@ -105,26 +107,26 @@ sCmsSGcb9ZkEQfRNGTmFFthkcnfTU9mKh8oGc/a9r0DDgYcPSCgqERt2fgiBrt85 /PXFBB3q2nX2XXqFRhqeN9eOlHBQ5EoZh8GUp7vJyxp5eAS9g2KVtCBwTDElQt4D 4hu+QuzzEmoWY9w1R+hblNu/37mWkzFFrLqYlkNU2vbKkuWMOTg= -----END CERTIFICATE-----"""; - var expected = "eb2611a447085322b206fa61d4bc5869b4a55657"; + var expected = "eb2611a447085322b206fa61d4bc5869b4a55657"; - var fingerprint = Crypt.fingerprint_certificate(pem); - // SHA1 - assert(fingerprint.length == 20); + var fingerprint = Crypt.fingerprint_certificate (pem); + // SHA1 + assert (fingerprint.length == 20); - var sb = new StringBuilder.sized(20*2); - foreach(var b in fingerprint) { - sb.append_printf("%02x", b); - } + var sb = new StringBuilder.sized (20 * 2); + foreach (var b in fingerprint) { + sb.append_printf ("%02x", b); + } - assert(sb.str == expected); + assert (sb.str == expected); } -public static void main(string[] args) { - Test.init(ref args); +public static void main (string[] args) { + Test.init (ref args); - Test.add_func("/mconn-crypt-vala/generated", test_generate); - Test.add_func("/mconn-crypt-vala/load", test_generate_load); - Test.add_func("/mconn-crypt-vala/verify-cn", test_custom_cn); - Test.add_func("/mconn-crypt-vala/fingerprint", test_fingerprint); - Test.run(); + Test.add_func ("/mconn-crypt-vala/generated", test_generate); + Test.add_func ("/mconn-crypt-vala/load", test_generate_load); + Test.add_func ("/mconn-crypt-vala/verify-cn", test_custom_cn); + Test.add_func ("/mconn-crypt-vala/fingerprint", test_fingerprint); + Test.run (); } \ No newline at end of file diff --git a/test/mconn-utils-test.vala b/test/mconn-utils-test.vala index ee527a9..840daba 100644 --- a/test/mconn-utils-test.vala +++ b/test/mconn-utils-test.vala @@ -1,57 +1,55 @@ -void test_find_urls_simple() { - var urls = Utils.find_urls("https://en.m.wikipedia.org/wiki/Isle_of_Man via DuckDuckGo for Android"); +void test_find_urls_simple () { + var urls = Utils.find_urls ("https://en.m.wikipedia.org/wiki/Isle_of_Man via DuckDuckGo for Android"); - assert(urls != null); - assert(urls.length == 1); + assert (urls != null); + assert (urls.length == 1); - assert(urls[0] == "https://en.m.wikipedia.org/wiki/Isle_of_Man"); + assert (urls[0] == "https://en.m.wikipedia.org/wiki/Isle_of_Man"); } -void test_find_urls_extract() { - var urls = Utils.find_urls("Foo bar baz?\n\nhttp://foo.bar.com/123/345/abcd\n\nShared from my Google cards"); +void test_find_urls_extract () { + var urls = Utils.find_urls ("Foo bar baz?\n\nhttp://foo.bar.com/123/345/abcd\n\nShared from my Google cards"); - assert(urls != null); - assert(urls.length == 1); + assert (urls != null); + assert (urls.length == 1); - assert(urls[0] == "http://foo.bar.com/123/345/abcd"); + assert (urls[0] == "http://foo.bar.com/123/345/abcd"); } -void test_find_urls_many() { - var urls = Utils.find_urls("https://foo.bar.com http://google.biz http://www.funny.io"); +void test_find_urls_many () { + var urls = Utils.find_urls ("https://foo.bar.com http://google.biz http://www.funny.io"); - assert(urls != null); - assert(urls.length == 3); + assert (urls != null); + assert (urls.length == 3); - assert(urls[0] == "https://foo.bar.com"); - assert(urls[1] == "http://google.biz"); - assert(urls[2] == "http://www.funny.io"); + assert (urls[0] == "https://foo.bar.com"); + assert (urls[1] == "http://google.biz"); + assert (urls[2] == "http://www.funny.io"); } -void test_find_urls_none() { - var urls = Utils.find_urls("baz bar \nbar.com foo "); +void test_find_urls_none () { + var urls = Utils.find_urls ("baz bar \nbar.com foo "); - assert(urls != null); - assert(urls.length == 0); + assert (urls != null); + assert (urls.length == 0); } -void test_find_urls_special() { - var urls = Utils.find_urls("http://foo.bar.com/123,345%20,,,/foo.html"); +void test_find_urls_special () { + var urls = Utils.find_urls ("http://foo.bar.com/123,345%20,,,/foo.html"); - assert(urls != null); - assert(urls.length == 1); + assert (urls != null); + assert (urls.length == 1); - assert(urls[0] == "http://foo.bar.com/123,345%20,,,/foo.html"); + assert (urls[0] == "http://foo.bar.com/123,345%20,,,/foo.html"); } +public static void main (string[] args) { + Test.init (ref args); - -public static void main(string[] args) { - Test.init(ref args); - - Test.add_func("/mconn-utils/find-urls/simple", test_find_urls_simple); - Test.add_func("/mconn-utils/find-urls/extract", test_find_urls_extract); - Test.add_func("/mconn-utils/find-urls/many", test_find_urls_many); - Test.add_func("/mconn-utils/find-urls/none", test_find_urls_none); - Test.add_func("/mconn-utils/find-urls/special", test_find_urls_special); - Test.run(); + Test.add_func ("/mconn-utils/find-urls/simple", test_find_urls_simple); + Test.add_func ("/mconn-utils/find-urls/extract", test_find_urls_extract); + Test.add_func ("/mconn-utils/find-urls/many", test_find_urls_many); + Test.add_func ("/mconn-utils/find-urls/none", test_find_urls_none); + Test.add_func ("/mconn-utils/find-urls/special", test_find_urls_special); + Test.run (); } \ No newline at end of file diff --git a/uncrustify.cfg b/uncrustify.cfg new file mode 100644 index 0000000..c05b89d --- /dev/null +++ b/uncrustify.cfg @@ -0,0 +1,1645 @@ +# Uncrustify 0.60 +# Rules for vala +# Version: 0.5 +# Refactored to match the style used on this project: https://github.com/GNOME/vala + +# +# General options +# + +# The type of line endings +newlines = auto # auto/lf/crlf/cr + +# The original size of tabs in the input +input_tab_size = 8 # number + +# The size of tabs in the output (only used if align_with_tabs=true) +output_tab_size = 4 # number + +# The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn) +string_escape_char = 92 # number + +# Alternate string escape char for Pawn. Only works right before the quote char. +string_escape_char2 = 0 # number + +# Allow interpreting '>=' and '>>=' as part of a template in 'void f(list>=val);'. +# If true (default), 'assert(x<0 && y>=3)' will be broken. +# Improvements to template detection may make this option obsolete. +tok_split_gte = false # false/true + +# Control what to do with the UTF-8 BOM (recommend 'remove') +utf8_bom = ignore # ignore/add/remove/force + +# If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8 +utf8_byte = false # false/true + +# Force the output encoding to UTF-8 +utf8_force = false # false/true + +# +# Indenting +# + +# The number of columns to indent per level. +# Usually 2, 3, 4, or 8. +indent_columns = 4 # number + +# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents. +# For FreeBSD, this is set to 4. Negative value is absolute and not increased for each ( level +indent_continue = 0 # number + +# How to use tabs when indenting code +# 0=spaces only +# 1=indent with tabs to brace level, align with spaces +# 2=indent and align with tabs, using spaces when not on a tabstop +indent_with_tabs = 0 # number + +# Comments that are not a brace level are indented with tabs on a tabstop. +# Requires indent_with_tabs=2. If false, will use spaces. +indent_cmt_with_tabs = false # false/true + +# Whether to indent strings broken by '\' so that they line up +indent_align_string = false # false/true + +# The number of spaces to indent multi-line XML strings. +# Requires indent_align_string=True +indent_xml_string = 0 # number + +# Spaces to indent '{' from level +indent_brace = 0 # number + +# Whether braces are indented to the body level +indent_braces = false # false/true + +# Disabled indenting function braces if indent_braces is true +indent_braces_no_func = false # false/true + +# Disabled indenting class braces if indent_braces is true +indent_braces_no_class = false # false/true + +# Disabled indenting struct braces if indent_braces is true +indent_braces_no_struct = false # false/true + +# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. +indent_brace_parent = false # false/true + +# Whether the 'namespace' body is indented +indent_namespace = true # false/true + +# The number of spaces to indent a namespace block +indent_namespace_level = 0 # number + +# If the body of the namespace is longer than this number, it won't be indented. +# Requires indent_namespace=true. Default=0 (no limit) +indent_namespace_limit = 0 # number + +# Whether the 'extern "C"' body is indented +indent_extern = false # false/true + +# Whether the 'class' body is indented +indent_class = true # false/true + +# Whether to indent the stuff after a leading class colon +indent_class_colon = false # false/true +# Whether to indent the stuff after a leading class initializer colon +indent_constr_colon = false # false/true + +# Virtual indent from the ':' for member initializers. Default is 2 +indent_ctor_init_leading = 2 # number + +# Additional indenting for constructor initializer list +indent_ctor_init = 0 # number + +# False=treat 'else\nif' as 'else if' for indenting purposes +# True=indent the 'if' one level +indent_else_if = false # false/true + +# Amount to indent variable declarations after a open brace. neg=relative, pos=absolute +indent_var_def_blk = 0 # number + +# Indent continued variable declarations instead of aligning. +indent_var_def_cont = false # false/true + +# True: force indentation of function definition to start in column 1 +# False: use the default behavior +indent_func_def_force_col1 = false # false/true + +# True: indent continued function call parameters one indent level +# False: align parameters under the open paren +indent_func_call_param = false # false/true + +# Same as indent_func_call_param, but for function defs +indent_func_def_param = false # false/true + +# Same as indent_func_call_param, but for function protos +indent_func_proto_param = false # false/true + +# Same as indent_func_call_param, but for class declarations +indent_func_class_param = false # false/true + +# Same as indent_func_call_param, but for class variable constructors +indent_func_ctor_var_param = false # false/true + +# Same as indent_func_call_param, but for templates +indent_template_param = false # false/true + +# Double the indent for indent_func_xxx_param options +indent_func_param_double = false # false/true + +# Indentation column for standalone 'const' function decl/proto qualifier +indent_func_const = 0 # number + +# Indentation column for standalone 'throw' function decl/proto qualifier +indent_func_throw = 0 # number + +# The number of spaces to indent a continued '->' or '.' +# Usually set to 0, 1, or indent_columns. +indent_member = 1 # number + +# Spaces to indent single line ('//') comments on lines before code +indent_sing_line_comments = 0 # number + +# If set, will indent trailing single line ('//') comments relative +# to the code instead of trying to keep the same absolute column +indent_relative_single_line_comments = false # false/true + +# Spaces to indent 'case' from 'switch' +# Usually 0 or indent_columns. +indent_switch_case = 0 # number + +# Spaces to shift the 'case' line, without affecting any other lines +# Usually 0. +indent_case_shift = 0 # number + +# Spaces to indent '{' from 'case'. +# By default, the brace will appear under the 'c' in case. +# Usually set to 0 or indent_columns. +indent_case_brace = 0 # number + +# Whether to indent comments found in first column +indent_col1_comment = false # false/true + +# How to indent goto labels +# >0 : absolute column where 1 is the leftmost column +# <=0 : subtract from brace indent +indent_label = 1 # number + +# Same as indent_label, but for access specifiers that are followed by a colon +indent_access_spec = 1 # number + +# Indent the code after an access specifier by one level. +# If set, this option forces 'indent_access_spec=0' +indent_access_spec_body = false # false/true + +# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended) +indent_paren_nl = false # false/true + +# Controls the indent of a close paren after a newline. +# 0: Indent to body level +# 1: Align under the open paren +# 2: Indent to the brace level +indent_paren_close = 0 # number + +# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren +indent_comma_paren = false # false/true + +# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren +indent_bool_paren = false # false/true + +# If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones +indent_first_bool_expr = false # false/true + +# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended) +indent_square_nl = false # false/true + +# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies +indent_preserve_sql = false # false/true + +# Align continued statements at the '='. Default=True +# If FALSE or the '=' is followed by a newline, the next line is indent one tab. +indent_align_assign = true # false/true + +# Indent OC blocks at brace level instead of usual rules. +indent_oc_block = false # false/true + +# Indent OC blocks in a message relative to the parameter name. +# 0=use indent_oc_block rules, 1+=spaces to indent +indent_oc_block_msg = 0 # number + +# Minimum indent for subsequent parameters +indent_oc_msg_colon = 0 # number + +# Objective C + +# If true, prioritize aligning with initial colon (and stripping spaces from lines, if necessary). +# Default is true. +indent_oc_msg_prioritize_first_colon = true + +# If indent_oc_block_msg and this option are on, blocks will be indented the way that Xcode does by default (from keyword if the parameter is on its own line; otherwise, from the previous indentation level). +indent_oc_block_msg_xcode_style = true + +# If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is relative to a msg keyword. +indent_oc_block_msg_from_keyword = true + +# If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is relative to a msg colon. +indent_oc_block_msg_from_colon = true + +# If indent_oc_block_msg and this option are on, blocks will be indented from where the block caret is. +indent_oc_block_msg_from_caret = true + +# If indent_oc_block_msg and this option are on, blocks will be indented from where the brace is. +indent_oc_block_msg_from_brace = true + +# +# Spacing options +# + +# Add or remove space around arithmetic operator '+', '-', '/', '*', etc +sp_arith = force # ignore/add/remove/force +# Add or remove space around assignment operator '=', '+=', etc +sp_assign = force # ignore/add/remove/force + +# Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign +sp_cpp_lambda_assign = force # ignore/add/remove/force + +# Add or remove space after the capture specification in C++11 lambda. +sp_cpp_lambda_paren = force # ignore/add/remove/force + +# Add or remove space around assignment operator '=' in a prototype +sp_assign_default = force # ignore/add/remove/force + +# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign. +sp_before_assign = force # ignore/add/remove/force + +# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign. +sp_after_assign = force # ignore/add/remove/force + +# Add or remove space around assignment '=' in enum +sp_enum_assign = force # ignore/add/remove/force + +# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign. +sp_enum_before_assign = ignore # ignore/add/remove/force + +# Add or remove space after assignment '=' in enum. Overrides sp_enum_assign. +sp_enum_after_assign = force # ignore/add/remove/force + +# Add or remove space around preprocessor '##' concatenation operator. Default=Add +sp_pp_concat = add # ignore/add/remove/force + +# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator. +sp_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'. +sp_before_pp_stringify = ignore # ignore/add/remove/force + +# Add or remove space around boolean operators '&&' and '||' +sp_bool = force # ignore/add/remove/force + +# Add or remove space around compare operator '<', '>', '==', etc +sp_compare = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')' +sp_inside_paren = remove # ignore/add/remove/force + +# Add or remove space between nested parens +sp_paren_paren = remove # ignore/add/remove/force + +# Add or remove space between back-to-back parens: ')(' vs ') (' +sp_cparen_oparen = remove # ignore/add/remove/force +# Whether to balance spaces inside nested parens +sp_balance_nested_parens = false # false/true + +# Add or remove space between ')' and '{' +sp_paren_brace = force # ignore/add/remove/force + +# Add or remove space before pointer star '*' +sp_before_ptr_star = remove # ignore/add/remove/force + +# Add or remove space before pointer star '*' that isn't followed by a variable name +# If set to 'ignore', sp_before_ptr_star is used instead. +sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force + +# Add or remove space between pointer stars '*' +sp_between_ptr_star = remove # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a word. +sp_after_ptr_star = force # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by a func proto/def. +sp_after_ptr_star_func = force # ignore/add/remove/force + +# Add or remove space after a pointer star '*', if followed by an open paren (function types). +sp_ptr_star_paren = force # ignore/add/remove/force + +# Add or remove space before a pointer star '*', if followed by a func proto/def. +sp_before_ptr_star_func = force # ignore/add/remove/force + +# Add or remove space before a reference sign '&' +sp_before_byref = force # ignore/add/remove/force + +# Add or remove space before a reference sign '&' that isn't followed by a variable name +# If set to 'ignore', sp_before_byref is used instead. +sp_before_unnamed_byref = ignore # ignore/add/remove/force + +# Add or remove space after reference sign '&', if followed by a word. +sp_after_byref = ignore # ignore/add/remove/force + +# Add or remove space after a reference sign '&', if followed by a func proto/def. +sp_after_byref_func = remove # ignore/add/remove/force + +# Add or remove space before a reference sign '&', if followed by a func proto/def. +sp_before_byref_func = force # ignore/add/remove/force + +# Add or remove space between type and word. Default=Force +sp_after_type = force # ignore/add/remove/force + +# Add or remove space before the paren in the D constructs 'template Foo(' and 'class Foo('. +sp_before_template_paren = ignore # ignore/add/remove/force + +# Add or remove space in 'template <' vs 'template<'. +# If set to ignore, sp_before_angle is used. +sp_template_angle = ignore # ignore/add/remove/force + +# Add or remove space before '<>' +sp_before_angle = remove # ignore/add/remove/force + +# Add or remove space inside '<' and '>' +sp_inside_angle = remove # ignore/add/remove/force + +# Add or remove space after '<>' +sp_after_angle = remove # ignore/add/remove/force + +# Add or remove space between '<>' and '(' as found in 'new List();' +sp_angle_paren = remove # ignore/add/remove/force + +# Add or remove space between '<>' and a word as in 'List m;' +sp_angle_word = force # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add +sp_angle_shift = add # ignore/add/remove/force + +# Permit removal of the space between '>>' in 'foo >' (C++11 only). Default=False +# sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = false # false/true + +# Add or remove space before '(' of 'if', 'for', 'switch', and 'while' +sp_before_sparen = force # ignore/add/remove/force + +# Add or remove space inside if-condition '(' and ')' +sp_inside_sparen = remove # ignore/add/remove/force + +# Add or remove space before if-condition ')'. Overrides sp_inside_sparen. +sp_inside_sparen_close = ignore # ignore/add/remove/force + +# Add or remove space before if-condition '('. Overrides sp_inside_sparen. +sp_inside_sparen_open = ignore # ignore/add/remove/force + +# Add or remove space after ')' of 'if', 'for', 'switch', and 'while' +sp_after_sparen = remove # ignore/add/remove/force + +# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while' +sp_sparen_brace = force # ignore/add/remove/force + +# Add or remove space between 'invariant' and '(' in the D language. +sp_invariant_paren = ignore # ignore/add/remove/force + +# Add or remove space after the ')' in 'invariant (C) c' in the D language. +sp_after_invariant_paren = ignore # ignore/add/remove/force + +# Add or remove space before empty statement ';' on 'if', 'for' and 'while' +sp_special_semi = remove # ignore/add/remove/force + +# Add or remove space before ';'. Default=Remove +sp_before_semi = remove # ignore/add/remove/force + +# Add or remove space before ';' in non-empty 'for' statements +sp_before_semi_for = remove # ignore/add/remove/force + +# Add or remove space before a semicolon of an empty part of a for statement. +sp_before_semi_for_empty = force # ignore/add/remove/force + +# Add or remove space after ';', except when followed by a comment. Default=Add +sp_after_semi = add # ignore/add/remove/force + +# Add or remove space after ';' in non-empty 'for' statements. Default=Force +sp_after_semi_for = force # ignore/add/remove/force + +# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; ). +sp_after_semi_for_empty = force # ignore/add/remove/force + +# Add or remove space before '[' (except '[]') +sp_before_square = remove # ignore/add/remove/force + +# Add or remove space before '[]' +sp_before_squares = remove # ignore/add/remove/force + +# Add or remove space inside a non-empty '[' and ']' +sp_inside_square = remove # ignore/add/remove/force + +# Add or remove space after ',' +sp_after_comma = force # ignore/add/remove/force + +# Add or remove space before ',' +sp_before_comma = remove # ignore/add/remove/force + +# Add or remove space between an open paren and comma: '(,' vs '( ,' +sp_paren_comma = force # ignore/add/remove/force + +# Add or remove space before the variadic '...' when preceded by a non-punctuator +sp_before_ellipsis = remove # ignore/add/remove/force + +# Add or remove space after class ':' +sp_after_class_colon = force # ignore/add/remove/force + +# Add or remove space before class ':' +sp_before_class_colon = force # ignore/add/remove/force + +# Add or remove space after class constructor ':' +sp_after_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before class constructor ':' +sp_before_constr_colon = ignore # ignore/add/remove/force + +# Add or remove space before case ':'. Default=Remove +sp_before_case_colon = remove # ignore/add/remove/force + +# Add or remove space between 'operator' and operator sign +sp_after_operator = force # ignore/add/remove/force + +# Add or remove space between the operator symbol and the open paren, as in 'operator ++(' +sp_after_operator_sym = ignore # ignore/add/remove/force + +# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a' +sp_after_cast = force # ignore/add/remove/force + +# Add or remove spaces inside cast parens +sp_inside_paren_cast = remove # ignore/add/remove/force + +# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)' +sp_cpp_cast_paren = ignore # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '(' +sp_sizeof_paren = force # ignore/add/remove/force + +# Add or remove space after the tag keyword (Pawn) +sp_after_tag = ignore # ignore/add/remove/force + +# Add or remove space inside enum '{' and '}' +sp_inside_braces_enum = force # ignore/add/remove/force + +# Add or remove space inside struct/union '{' force '}' +sp_inside_braces_struct = force # ignore/add/remove/force + +# Add or remove space inside '{' and '}' +sp_inside_braces = force # ignore/add/remove/force + +# Add or remove space inside '{}' +sp_inside_braces_empty = remove # ignore/add/remove/force + +# Add or remove space between return type and function name +# A minimum of 1 is forced except for pointer return types. +sp_type_func = remove # ignore/add/remove/force + +# Add or remove space between function name and '(' on function declaration +sp_func_proto_paren = force # ignore/add/remove/force + +# CARL duplicates ERROR ?? +# Add or remove space between function name and '(' on function definition +sp_func_def_paren = force # ignore/add/remove/force + +# Add or remove space inside empty function '()' +sp_inside_fparens = remove # ignore/add/remove/force + +# Add or remove space inside function '(' and ')' +sp_inside_fparen = remove # ignore/add/remove/force + +# Add or remove space inside the first parens in the function type: 'void (*x)(...)' +sp_inside_tparen = remove # ignore/add/remove/force + +# Add or remove between the parens in the function type: 'void (*x)(...)' +sp_after_tparen_close = remove # ignore/add/remove/force + +# Add or remove space between ']' and '(' when part of a function call. +sp_square_fparen = force # ignore/add/remove/force + +# Add or remove space between ')' and '{' of function +sp_fparen_brace = force # ignore/add/remove/force + +# Add or remove space between function name and '(' on function calls +sp_func_call_paren = force # ignore/add/remove/force + +# Add or remove space between function name and '()' on function calls without parameters. +# If set to 'ignore' (the default), sp_func_call_paren is used. +sp_func_call_paren_empty = force # ignore/add/remove/force + +# Add or remove space between the user function name and '(' on function calls +# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file. +sp_func_call_user_paren = ignore # ignore/add/remove/force + +# Add or remove space between a constructor/destructor and the open paren +sp_func_class_paren = force # ignore/add/remove/force + +# Add or remove space between 'return' and '(' +sp_return_paren = force # ignore/add/remove/force + +# Add or remove space between '__attribute__' and '(' +sp_attribute_paren = force # ignore/add/remove/force + +# Add or remove space between 'defined' and '(' in '#if defined (FOO)' +sp_defined_paren = force # ignore/add/remove/force + +# Add or remove space between 'throw' and '(' in 'throw (something)' +sp_throw_paren = force # ignore/add/remove/force + +# Add or remove space between 'throw' and anything other than '(' as in '@throw [...];' +sp_after_throw = force # ignore/add/remove/force + +# Add or remove space between 'catch' and '(' in 'catch (something) { }' +# If set to ignore, sp_before_sparen is used. +sp_catch_paren = force # ignore/add/remove/force + +# D +# Add or remove space between 'version' and '(' in 'version (something) { }' (D language) +# If set to ignore, sp_before_sparen is used. +sp_version_paren = ignore # ignore/add/remove/force + +# D +# Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language) +# If set to ignore, sp_before_sparen is used. +sp_scope_paren = ignore # ignore/add/remove/force + +# Add or remove space between macro and value +sp_macro = ignore # ignore/add/remove/force + +# MACRO +# Add or remove space between macro function ')' and value +sp_macro_func = ignore # ignore/add/remove/force + +# Add or remove space between 'else' and '{' if on the same line +sp_else_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'else' if on the same line +sp_brace_else = force # ignore/add/remove/force + +# Add or remove space between '}' and the name of a typedef on the same line +sp_brace_typedef = force # ignore/add/remove/force + +# Add or remove space between 'catch' and '{' if on the same line +sp_catch_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'catch' if on the same line +sp_brace_catch = force # ignore/add/remove/force + +# Add or remove space between 'finally' and '{' if on the same line +sp_finally_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'finally' if on the same line +sp_brace_finally = force # ignore/add/remove/force + +# Add or remove space between 'try' and '{' if on the same line +sp_try_brace = force # ignore/add/remove/force + +# Add or remove space between get/set and '{' if on the same line +sp_getset_brace = force # ignore/add/remove/force + +# CARL TODO + +# Add or remove space between a variable and '{' for C++ uniform initialization +sp_word_brace = ignore + +# Add or remove space between a variable and '{' for a namespace +sp_word_brace_ns = force + +# C++ +# Add or remove space before the '::' operator +sp_before_dc = remove # ignore/add/remove/force + +# C++ +# Add or remove space after the '::' operator +sp_after_dc = remove # ignore/add/remove/force + +# Add or remove around the D named array initializer ':' operator +sp_d_array_colon = ignore # ignore/add/remove/force + +# Add or remove space after the '!' (not) operator. Default=Remove +sp_not = remove # ignore/add/remove/force + +# Add or remove space after the '~' (invert) operator. Default=Remove +sp_inv = remove # ignore/add/remove/force + +# Add or remove space after the '&' (address-of) operator. Default=Remove +# This does not affect the spacing after a '&' that is part of a type. +sp_addr = remove # ignore/add/remove/force + +# Add or remove space around the '.' or '->' operators. Default=Remove +sp_member = remove # ignore/add/remove/force + +# Add or remove space after the '*' (dereference) operator. Default=Remove +# This does not affect the spacing after a '*' that is part of a type. +sp_deref = remove # ignore/add/remove/force + +# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove +sp_sign = remove # ignore/add/remove/force + +# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove +sp_incdec = remove # ignore/add/remove/force + +# Add or remove space before a backslash-newline at the end of a line. Default=Add +sp_before_nl_cont = add # ignore/add/remove/force + +# Obj c +# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;' +sp_after_oc_scope = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space after the colon in message specs +# '-(int) f:(int) x;' vs '-(int) f: (int) x;' +sp_after_oc_colon = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space before the colon in message specs +# '-(int) f: (int) x;' vs '-(int) f : (int) x;' +sp_before_oc_colon = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space after the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};' +sp_after_oc_dict_colon = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space before the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};' +sp_before_oc_dict_colon = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space after the colon in message specs +# '[object setValue:1];' vs '[object setValue: 1];' +sp_after_send_oc_colon = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space before the colon in message specs +# '[object setValue:1];' vs '[object setValue :1];' +sp_before_send_oc_colon = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space after the (type) in message specs +# '-(int)f: (int) x;' vs '-(int)f: (int)x;' +sp_after_oc_type = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space after the first (type) in message specs +# '-(int) f:(int)x;' vs '-(int)f:(int)x;' +sp_after_oc_return_type = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space between '@selector' and '(' +# '@selector(msgName)' vs '@selector (msgName)' +# Also applies to @protocol() constructs +sp_after_oc_at_sel = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space between '@selector(x)' and the following word +# '@selector(foo) a:' vs '@selector(foo)a:' +sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space inside '@selector' parens +# '@selector(foo)' vs '@selector( foo )' +# Also applies to @protocol() constructs +sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space before a block pointer caret +# '^int (int arg){...}' vs. ' ^int (int arg){...}' +sp_before_oc_block_caret = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space after a block pointer caret +# '^int (int arg){...}' vs. '^ int (int arg){...}' +sp_after_oc_block_caret = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space between the receiver and selector in a message. +# '[receiver selector ...]' +sp_after_oc_msg_receiver = ignore # ignore/add/remove/force + +# Obj c +# Add or remove space after @property. +sp_after_oc_property = ignore # ignore/add/remove/force + +# Add or remove space around the ':' in 'b ? t : f' +sp_cond_colon = force # ignore/add/remove/force +# TODO + +# Add or remove space before the ':' in 'b ? t : f'. Overrides sp_cond_colon. +sp_cond_colon_before = force +# Add or remove space after the ':' in 'b ? t : f'. Overrides sp_cond_colon. +sp_cond_colon_after = force +# Add or remove space around the '?' in 'b ? t : f' +sp_cond_question = force + +# Add or remove space before the '?' in 'b ? t : f'. Overrides sp_cond_question. +sp_cond_question_before = force + +# Add or remove space after the '?' in 'b ? t : f'. Overrides sp_cond_question. +sp_cond_question_after = force + +# In the abbreviated ternary form (a ?: b), add/remove space between ? and :.'. Overrides all other sp_cond_* options. +sp_cond_ternary_short = force + +# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here. +sp_case_label = force # ignore/add/remove/force + +# Control the space around the D '..' operator. +sp_range = ignore # ignore/add/remove/force + +# Control the spacing after ':' in 'for (TYPE VAR : EXPR)' (Java) +sp_after_for_colon = ignore # ignore/add/remove/force + +# Control the spacing before ':' in 'for (TYPE VAR : EXPR)' (Java) +sp_before_for_colon = ignore # ignore/add/remove/force + +# Control the spacing in 'extern (C)' (D) +sp_extern_paren = ignore # ignore/add/remove/force + +# Control the space after the opening of a C++ comment '// A' vs '//A' +sp_cmt_cpp_start = force # ignore/add/remove/force + +# Controls the spaces between #else or #endif and a trailing comment +sp_endif_cmt = remove # ignore/add/remove/force + +# Controls the spaces after 'new', 'delete', and 'delete[]' +sp_after_new = force # ignore/add/remove/force + +# Controls the spaces before a trailing or embedded comment +sp_before_tr_emb_cmt = force # ignore/add/remove/force + +# Number of spaces before a trailing or embedded comment +sp_num_before_tr_emb_cmt = 0 # number + +# Control space between a Java annotation and the open paren. +sp_annotation_paren = ignore # ignore/add/remove/force + +# +# Code alignment (not left column spaces/tabs) +# + +# Whether to keep non-indenting tabs +align_keep_tabs = false # false/true + +# Whether to use tabs for aligning +align_with_tabs = false # false/true + +# Whether to bump out to the next tab when aligning +align_on_tabstop = false # false/true + +# Whether to left-align numbers +align_number_left = false # false/true + +# TODO DOC +# Whether to keep whitespace not required for alignment. +align_keep_extra_space = true + +# Align variable definitions in prototypes and functions +align_func_params = false # false/true + +# Align parameters in single-line functions that have the same name. +# The function names must already be aligned with each other. +align_same_func_call_params = false # false/true + +# The span for aligning variable definitions (0=don't align) +align_var_def_span = 0 # number + +# How to align the star in variable definitions. +# 0=Part of the type 'void * foo;' +# 1=Part of the variable 'void *foo;' +# 2=Dangling 'void *foo;' +align_var_def_star_style = 0 # number + +# How to align the '&' in variable definitions. +# 0=Part of the type +# 1=Part of the variable +# 2=Dangling +align_var_def_amp_style = 0 # number + +# The threshold for aligning variable definitions (0=no limit) +align_var_def_thresh = 0 # number + +# The gap for aligning variable definitions +align_var_def_gap = 0 # number + +# Whether to align the colon in struct bit fields +align_var_def_colon = false # false/true + +# Whether to align any attribute after the variable name +align_var_def_attribute = false # false/true + +# Whether to align inline struct/enum/union variable definitions +align_var_def_inline = false # false/true + +# The span for aligning on '=' in assignments (0=don't align) +align_assign_span = 0 # number + +# The threshold for aligning on '=' in assignments (0=no limit) +align_assign_thresh = 0 # number + +# The span for aligning on '=' in enums (0=don't align) +align_enum_equ_span = 0 # number + +# The threshold for aligning on '=' in enums (0=no limit) +align_enum_equ_thresh = 0 # number + +# The span for aligning struct/union (0=don't align) +align_var_struct_span = 0 # number + +# The threshold for aligning struct/union member definitions (0=no limit) +align_var_struct_thresh = 0 # number + +# The gap for aligning struct/union member definitions +align_var_struct_gap = 0 # number + +# The span for aligning struct initializer values (0=don't align) +align_struct_init_span = 0 # number + +# The minimum space between the type and the synonym of a typedef +align_typedef_gap = 0 # number + +# The span for aligning single-line typedefs (0=don't align) +align_typedef_span = 0 # number + +# How to align typedef'd functions with other typedefs +# 0: Don't mix them at all +# 1: align the open paren with the types +# 2: align the function type name with the other type names +align_typedef_func = 0 # number + +# Controls the positioning of the '*' in typedefs. Just try it. +# 0: Align on typedef type, ignore '*' +# 1: The '*' is part of type name: typedef int *pint; +# 2: The '*' is part of the type, but dangling: typedef int *pint; +align_typedef_star_style = 0 # number + +# Controls the positioning of the '&' in typedefs. Just try it. +# 0: Align on typedef type, ignore '&' +# 1: The '&' is part of type name: typedef int &pint; +# 2: The '&' is part of the type, but dangling: typedef int &pint; +align_typedef_amp_style = 0 # number + +# The span for aligning comments that end lines (0=don't align) +align_right_cmt_span = 0 # number + +# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment +align_right_cmt_mix = false # false/true + +# If a trailing comment is more than this number of columns away from the text it follows, +# it will qualify for being aligned. This has to be > 0 to do anything. +align_right_cmt_gap = 0 # number + +# Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore) +align_right_cmt_at_col = 0 # number + +# The span for aligning function prototypes (0=don't align) +align_func_proto_span = 0 # number + +# Minimum gap between the return type and the function name. +align_func_proto_gap = 0 # number + +# Align function protos on the 'operator' keyword instead of what follows +align_on_operator = false # false/true + +# Whether to mix aligning prototype and variable declarations. +# If true, align_var_def_XXX options are used instead of align_func_proto_XXX options. +align_mix_var_proto = false # false/true + +# Align single-line functions with function prototypes, uses align_func_proto_span +align_single_line_func = false # false/true + +# Aligning the open brace of single-line functions. +# Requires align_single_line_func=true, uses align_func_proto_span +align_single_line_brace = false # false/true + +# Gap for align_single_line_brace. +align_single_line_brace_gap = 0 # number + +# The span for aligning ObjC msg spec (0=don't align) +align_oc_msg_spec_span = 0 # number + +# Whether to align macros wrapped with a backslash and a newline. +# This will not work right if the macro contains a multi-line comment. +align_nl_cont = false # false/true + +# # Align macro functions and variables together +align_pp_define_together = false # false/true + +# The minimum space between label and value of a preprocessor define +align_pp_define_gap = 0 # number + +# The span for aligning on '#define' bodies (0=don't align) +align_pp_define_span = 0 # number + +# Align lines that start with '<<' with previous '<<'. Default=true +align_left_shift = true # false/true + +# Span for aligning parameters in an Obj-C message call on the ':' (0=don't align) +align_oc_msg_colon_span = 0 # number + +# If true, always align with the first parameter, even if it is too short. +align_oc_msg_colon_first = false # false/true + +# Aligning parameters in an Obj-C '+' or '-' declaration on the ':' +align_oc_decl_colon = false # false/true + +# +# Newline adding and removing options +# + +# Whether to collapse empty blocks between '{' and '}' +nl_collapse_empty_body = false # false/true + +# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };' +nl_assign_leave_one_liners = true # false/true + +# Don't split one-line braced statements inside a class xx { } body +nl_class_leave_one_liners = false # false/true + +# Don't split one-line enums: 'enum foo { BAR = 15 };' +nl_enum_leave_one_liners = false # false/true + +# Don't split one-line get or set functions +nl_getset_leave_one_liners = false # false/true + +# Don't split one-line function definitions - 'int foo() { return 0; }' +nl_func_leave_one_liners = false # false/true + +# Don't split one-line if/else statements - 'if(a) b++;' +nl_if_leave_one_liners = false # false/true + +# Don't split one-line OC messages +nl_oc_msg_leave_one_liner = false # false/true + +# Add or remove newlines at the start of the file +nl_start_of_file = ignore # ignore/add/remove/force + +# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force' +nl_start_of_file_min = 0 # number + +# Add or remove newline at the end of the file +nl_end_of_file = force # ignore/add/remove/force + +# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force') +nl_end_of_file_min = 0 # number + +# Add or remove newline between '=' and '{' +nl_assign_brace = ignore # ignore/add/remove/force + +# Add or remove newline between '=' and '[' (D only) +nl_assign_square = ignore # ignore/add/remove/force + +# Add or remove newline after '= [' (D only). Will also affect the newline before the ']' +nl_after_square_assign = ignore # ignore/add/remove/force + +# The number of blank lines after a block of variable definitions at the top of a function body +# 0 = No change (default) +nl_func_var_def_blk = 0 # number + +# The number of newlines before a block of typedefs +# 0 = No change (default) +nl_typedef_blk_start = 0 # number + +# The number of newlines after a block of typedefs +# 0 = No change (default) +nl_typedef_blk_end = 0 # number + +# The maximum consecutive newlines within a block of typedefs +# 0 = No change (default) +nl_typedef_blk_in = 0 # number + +# The number of newlines before a block of variable definitions not at the top of a function body +# 0 = No change (default) +nl_var_def_blk_start = 0 # number + +# The number of newlines after a block of variable definitions not at the top of a function body +# 0 = No change (default) +nl_var_def_blk_end = 0 # number + +# The maximum consecutive newlines within a block of variable definitions +# 0 = No change (default) +nl_var_def_blk_in = 0 # number + +# Add or remove newline between a function call's ')' and '{', as in: +# list_for_each(item, &list) { } +nl_fcall_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'enum' and '{' +nl_enum_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'struct and '{' +nl_struct_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'union' and '{' +nl_union_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'if' and '{' +nl_if_brace = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'else' +nl_brace_else = remove # ignore/add/remove/force + +# Add or remove newline between 'else if' and '{' +# If set to ignore, nl_if_brace is used instead +nl_elseif_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'else' and '{' +nl_else_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'else' and 'if' +nl_else_if = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'finally' +nl_brace_finally = remove # ignore/add/remove/force + +# Add or remove newline between 'finally' and '{' +nl_finally_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'try' and '{' +nl_try_brace = remove # ignore/add/remove/force + +# Add or remove newline between get/set and '{' +nl_getset_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'for' and '{' +nl_for_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'catch' and '{' +nl_catch_brace = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'catch' +nl_brace_catch = remove # ignore/add/remove/force + +# Add or remove newline between '}' and ']' +nl_brace_square = remove # ignore/add/remove/force + +# Add or remove newline between '}' and ')' in a function invocation +nl_brace_fparen = remove # ignore/add/remove/force +# Add or remove newline between 'while' and '{' +nl_while_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'scope (x)' and '{' (D) +nl_scope_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'unittest' and '{' (D) +nl_unittest_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'version (x)' and '{' (D) +nl_version_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'using' and '{' +nl_using_brace = remove # ignore/add/remove/force + +# Add or remove newline between two open or close braces. +# Due to general newline/brace handling, REMOVE may not work. +nl_brace_brace = ignore # ignore/add/remove/force + +# Add or remove newline between 'do' and '{' +nl_do_brace = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'while' of 'do' statement +nl_brace_while = remove # ignore/add/remove/force + +# Add or remove newline between 'switch' and '{' +nl_switch_brace = remove # ignore/add/remove/force + +# Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc. +# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace. +nl_multi_line_cond = false # false/true + +# Force a newline in a define after the macro name for multi-line defines. +nl_multi_line_define = false # false/true + +# Whether to put a newline before 'case' statement +nl_before_case = false # false/true + +# Add or remove newline between ')' and 'throw' +nl_before_throw = remove # ignore/add/remove/force + +# Whether to put a newline after 'case' statement +nl_after_case = false # false/true + +# Add or remove a newline between a case ':' and '{'. Overrides nl_after_case. +nl_case_colon_brace = ignore # ignore/add/remove/force + +# Newline between namespace and { +nl_namespace_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'template<>' and whatever follows. +nl_template_class = ignore # ignore/add/remove/force + +# Add or remove newline between 'class' and '{' +nl_class_brace = remove # ignore/add/remove/force + +# Add or remove newline after each ',' in the class base list +nl_class_init_args = remove # ignore/add/remove/force +# Add or remove newline after each ',' in the constructor member initialization +nl_class_init_args = remove # ignore/add/remove/force + +# Add or remove newline between return type and function name in a function definition +nl_func_type_name = remove # ignore/add/remove/force + +# Add or remove newline between return type and function name inside a class {} +# Uses nl_func_type_name or nl_func_proto_type_name if set to ignore. +nl_func_type_name_class = remove # ignore/add/remove/force + +# Add or remove newline between function scope and name in a definition +# Controls the newline after '::' in 'void A::f() { }' +nl_func_scope_name = ignore # ignore/add/remove/force + +# Add or remove newline between return type and function name in a prototype +nl_func_proto_type_name = remove # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' +nl_func_paren = remove # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the definition +nl_func_def_paren = remove # ignore/add/remove/force + +# Add or remove newline after '(' in a function declaration +nl_func_decl_start = remove # ignore/add/remove/force + +# Add or remove newline after '(' in a function definition +nl_func_def_start = remove # ignore/add/remove/force + +# Overrides nl_func_decl_start when there is only one parameter. +nl_func_decl_start_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_start when there is only one parameter. +nl_func_def_start_single = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function declaration +nl_func_decl_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function definition +nl_func_def_args = ignore # ignore/add/remove/force + +# Add or remove newline before the ')' in a function declaration +nl_func_decl_end = remove # ignore/add/remove/force + +# Add or remove newline before the ')' in a function definition +nl_func_def_end = remove # ignore/add/remove/force + +# Overrides nl_func_decl_end when there is only one parameter. +nl_func_decl_end_single = ignore # ignore/add/remove/force + +# Overrides nl_func_def_end when there is only one parameter. +nl_func_def_end_single = ignore # ignore/add/remove/force + +# Add or remove newline between '()' in a function declaration. +nl_func_decl_empty = remove # ignore/add/remove/force + +# Add or remove newline between '()' in a function definition. +nl_func_def_empty = remove # ignore/add/remove/force + +# Whether to put each OC message parameter on a separate line +# See nl_oc_msg_leave_one_liner +nl_oc_msg_args = false # false/true + +# Add or remove newline between function signature and '{' +nl_fdef_brace = remove # ignore/add/remove/force + +# Add or remove newline between C++11 lambda signature and '{' +nl_cpp_ldef_brace = ignore # ignore/add/remove/force + +# Add or remove a newline between the return keyword and return expression. +nl_return_expr = remove # ignore/add/remove/force + +# Whether to put a newline after semicolons, except in 'for' statements +nl_after_semicolon = false # false/true + +# Whether to put a newline after brace open. +# This also adds a newline before the matching brace close. +nl_after_brace_open = true # false/true + +# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is +# placed between the open brace and a trailing single-line comment. +nl_after_brace_open_cmt = false # false/true + +# Whether to put a newline after a virtual brace open with a non-empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open = false # false/true + +# Whether to put a newline after a virtual brace open with an empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open_empty = false # false/true + +# Whether to put a newline after a brace close. +# Does not apply if followed by a necessary ';'. +nl_after_brace_close = false # false/true + +# Whether to put a newline after a virtual brace close. +# Would add a newline before return in: 'if (foo) a++; return;' +nl_after_vbrace_close = false # false/true + +# Control the newline between the close brace and 'b' in: 'struct { int a; } b;' +# Affects enums, unions, and structures. If set to ignore, uses nl_after_brace_close +nl_brace_struct_var = ignore # ignore/add/remove/force + +# Whether to alter newlines in '#define' macros +nl_define_macro = false # false/true + +# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif' +nl_squeeze_ifdef = false # false/true + +# Add or remove blank line before 'if' +nl_before_if = ignore # ignore/add/remove/force + +# Add or remove blank line after 'if' statement +nl_after_if = ignore # ignore/add/remove/force + +# Add or remove blank line before 'for' +nl_before_for = ignore # ignore/add/remove/force + +# Add or remove blank line after 'for' statement +nl_after_for = ignore # ignore/add/remove/force + +# Add or remove blank line before 'while' +nl_before_while = ignore # ignore/add/remove/force + +# Add or remove blank line after 'while' statement +nl_after_while = ignore # ignore/add/remove/force + +# Add or remove blank line before 'switch' +nl_before_switch = ignore # ignore/add/remove/force + +# Add or remove blank line after 'switch' statement +nl_after_switch = ignore # ignore/add/remove/force + +# Add or remove blank line before 'do' +nl_before_do = ignore # ignore/add/remove/force + +# Add or remove blank line after 'do/while' statement +nl_after_do = ignore # ignore/add/remove/force + +# Whether to double-space commented-entries in struct/enum +nl_ds_struct_enum_cmt = false # false/true + +# Whether to double-space before the close brace of a struct/union/enum +# (lower priority than 'eat_blanks_before_close_brace') +nl_ds_struct_enum_close_brace = false # false/true + +# Add or remove a newline around a class colon. +# Related to pos_class_colon, nl_class_init_args, and pos_comma. +nl_class_colon = ignore # ignore/add/remove/force + +# Add or remove a newline around a class constructor colon. +# Related to pos_constr_colon, nl_constr_init_args, and pos_constr_comma. +nl_constr_colon = ignore # ignore/add/remove/force + + +# Change simple unbraced if statements into a one-liner +# 'if(b)\n i++;' => 'if(b) i++;' +nl_create_if_one_liner = false # false/true + +# Change simple unbraced for statements into a one-liner +# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);' +nl_create_for_one_liner = false # false/true + +# Change simple unbraced while statements into a one-liner +# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);' +nl_create_while_one_liner = false # false/true + +# +# Positioning options +# + +# The position of arithmetic operators in wrapped expressions +pos_arith = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of assignment in wrapped expressions. +# Do not affect '=' followed by '{' +pos_assign = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of boolean operators in wrapped expressions +pos_bool = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of comparison operators in wrapped expressions +pos_compare = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of conditional (b ? t : f) operators in wrapped expressions +pos_conditional = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of the comma in wrapped expressions +pos_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of the comma in the class base list +pos_class_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of the comma in the constructor initialization list +pos_constr_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of colons between class and base class list +pos_class_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# The position of colons between constructor and member initialization +pos_constr_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force + +# +# Line Splitting options +# + +# Try to limit code width to N number of columns +code_width = 0 # number + +# Whether to fully split long 'for' statements at semi-colons +ls_for_split_full = false # false/true + +# Whether to fully split long function protos/calls at commas +ls_func_split_full = false # false/true + +# Whether to split lines as close to code_width as possible and ignore some groupings +ls_code_width = false # false/true + +# +# Blank line options +# + +# The maximum consecutive newlines +nl_max = 0 # number + +# The number of newlines after a function prototype, if followed by another function prototype +nl_after_func_proto = 0 # number + +# The number of newlines after a function prototype, if not followed by another function prototype +nl_after_func_proto_group = 2 # number + +# The number of newlines after '}' of a multi-line function body +nl_after_func_body = 2 # number + +# The number of newlines after '}' of a multi-line function body in a class declaration +nl_after_func_body_class = 2 # number + +# The number of newlines after '}' of a single line function body +nl_after_func_body_one_liner = 0 # number + +# The minimum number of newlines before a multi-line comment. +# Doesn't apply if after a brace open or another multi-line comment. +nl_before_block_comment = 0 # number + +# The minimum number of newlines before a single-line C comment. +# Doesn't apply if after a brace open or other single-line C comments. +nl_before_c_comment = 0 # number + +# The minimum number of newlines before a CPP comment. +# Doesn't apply if after a brace open or other CPP comments. +nl_before_cpp_comment = 0 # number + +# Whether to force a newline after a multi-line comment. +nl_after_multiline_comment = false # false/true + +# The number of newlines after '}' or ';' of a struct/enum/union definition +nl_after_struct = 0 # number + +# The number of newlines after '}' or ';' of a class definition +nl_after_class = 1 # number + +# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. +# Will not change the newline count if after a brace open. +# 0 = No change. +nl_before_access_spec = 0 # number + +# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label. +# 0 = No change. +nl_after_access_spec = 0 # number + +# The number of newlines between a function def and the function comment. +# 0 = No change. +nl_comment_func_def = 0 # number + +# The number of newlines after a try-catch-finally block that isn't followed by a brace close. +# 0 = No change. +nl_after_try_catch_finally = 0 # number + +# The number of newlines before and after a property, indexer or event decl. +# 0 = No change. +nl_around_cs_property = 0 # number + +# The number of newlines between the get/set/add/remove handlers in C#. +# 0 = No change. +nl_between_get_set = 0 # number + +# Add or remove newline between C# property and the '{' +nl_property_brace = ignore # ignore/add/remove/force + +# Whether to remove blank lines after '{' +eat_blanks_after_open_brace = false # false/true + +# Whether to remove blank lines before '}' +eat_blanks_before_close_brace = true # false/true + +# How aggressively to remove extra newlines not in preproc. +# 0: No change +# 1: Remove most newlines not handled by other config +# 2: Remove all newlines and reformat completely by config +nl_remove_extra_newlines = 0 # number + +# Whether to put a blank line before 'return' statements, unless after an open brace. +nl_before_return = false # false/true + +# Whether to put a blank line after 'return' statements, unless followed by a close brace. +nl_after_return = false # false/true + +# Whether to put a newline after a Java annotation statement. +# Only affects annotations that are after a newline. +nl_after_annotation = ignore # ignore/add/remove/force + +# Controls the newline between two annotations. +nl_between_annotation = ignore # ignore/add/remove/force + +# +# Code modifying options (non-whitespace) +# + +# Add or remove braces on single-line 'do' statement +mod_full_brace_do = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'for' statement +mod_full_brace_for = ignore # ignore/add/remove/force + +# Add or remove braces on single-line function definitions. (Pawn) +mod_full_brace_function = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'. +mod_full_brace_if = ignore # ignore/add/remove/force + +# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if. +# If any must be braced, they are all braced. If all can be unbraced, then the braces are removed. +mod_full_brace_if_chain = false # false/true + +# Don't remove braces around statements that span N newlines +mod_full_brace_nl = 0 # number + +# Add or remove braces on single-line 'while' statement +mod_full_brace_while = ignore # ignore/add/remove/force + +# Add or remove braces on single-line 'using ()' statement +mod_full_brace_using = ignore # ignore/add/remove/force + +# Add or remove unnecessary paren on 'return' statement +mod_paren_on_return = ignore # ignore/add/remove/force + +# Whether to change optional semicolons to real semicolons +mod_pawn_semicolon = false # false/true + +# Add parens on 'while' and 'if' statement around bools +mod_full_paren_if_bool = false # false/true + +# Whether to remove superfluous semicolons +mod_remove_extra_semicolon = false # false/true + +# If a function body exceeds the specified number of newlines and doesn't have a comment after +# the close brace, a comment will be added. +mod_add_long_function_closebrace_comment = 0 # number + +# If a namespace body exceeds the specified number of newlines and doesn't have a comment after +# the close brace, a comment will be added. +mod_add_long_namespace_closebrace_comment = 0 # number +# If a switch body exceeds the specified number of newlines and doesn't have a comment after +# the close brace, a comment will be added. +mod_add_long_switch_closebrace_comment = 0 # number + +# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after +# the #endif, a comment will be added. +mod_add_long_ifdef_endif_comment = 0 # number + +# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after +# the #else, a comment will be added. +mod_add_long_ifdef_else_comment = 0 # number + +# If TRUE, will sort consecutive single-line 'import' statements [Java, D] +mod_sort_import = false # false/true + +# If TRUE, will sort consecutive single-line 'using' statements [C#] +mod_sort_using = false # false/true + +# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C] +# This is generally a bad idea, as it may break your code. +mod_sort_include = false # false/true + +# If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace. +mod_move_case_break = false # false/true + +# Will add or remove the braces around a fully braced case statement. +# Will only remove the braces if there are no variable declarations in the block. +mod_case_brace = ignore # ignore/add/remove/force + +# If TRUE, it will remove a void 'return;' that appears as the last statement in a function. +mod_remove_empty_return = false # false/true + +# +# Comment modifications +# + +# Try to wrap comments at cmt_width columns +cmt_width = 0 # number + +# Set the comment reflow mode (default: 0) +# 0: no reflowing (apart from the line wrapping due to cmt_width) +# 1: no touching at all +# 2: full reflow +cmt_reflow_mode = 0 # number + +# If false, disable all multi-line comment changes, including cmt_width. keyword substitution, and leading chars. +# Default is true. +cmt_indent_multi = true # false/true + +# Whether to group c-comments that look like they are in a block +cmt_c_group = false # false/true + +# Whether to put an empty '/*' on the first line of the combined c-comment +cmt_c_nl_start = false # false/true + +# Whether to put a newline before the closing '*/' of the combined c-comment +cmt_c_nl_end = false # false/true + +# Whether to group cpp-comments that look like they are in a block +cmt_cpp_group = false # false/true + +# Whether to put an empty '/*' on the first line of the combined cpp-comment +cmt_cpp_nl_start = false # false/true + +# Whether to put a newline before the closing '*/' of the combined cpp-comment +cmt_cpp_nl_end = false # false/true + +# Whether to change cpp-comments into c-comments +cmt_cpp_to_c = false # false/true + +# Whether to put a star on subsequent comment lines +cmt_star_cont = false # false/true + +# The number of spaces to insert at the start of subsequent comment lines +cmt_sp_before_star_cont = 0 # number + +# The number of spaces to insert after the star on subsequent comment lines +cmt_sp_after_star_cont = 0 # number + +# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of +# the comment are the same length. Default=True +cmt_multi_check_last = true # false/true + +# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment. +# Will substitute $(filename) with the current file's name. +cmt_insert_file_header = "" # string + +# The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment. +# Will substitute $(filename) with the current file's name. +cmt_insert_file_footer = "" # string + +# The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment. +# Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff. +# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... } +cmt_insert_func_header = "" # string + +# The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment. +# Will substitute $(class) with the class name. +cmt_insert_class_header = "" # string + +# The filename that contains text to insert before a Obj-C message specification if the method isn't preceeded with a C/C++ comment. +# Will substitute $(message) with the function name and $(javaparam) with the javadoc @param and @return stuff. +cmt_insert_oc_msg_header = "" # string + +# If a preprocessor is encountered when stepping backwards from a function name, then +# this option decides whether the comment should be inserted. +# Affects cmt_insert_oc_msg_header, cmt_insert_func_header and cmt_insert_class_header. +cmt_insert_before_preproc = false # false/true + +# +# Preprocessor options +# + +# Control indent of preprocessors inside #if blocks at brace level 0 +pp_indent = ignore # ignore/add/remove/force + +# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false) +pp_indent_at_level = false # false/true + +# If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1. +pp_indent_count = 1 # number + +# Add or remove space after # based on pp_level of #if blocks +pp_space = ignore # ignore/add/remove/force + +# Sets the number of spaces added with pp_space +pp_space_count = 0 # number + +# The indent for #region and #endregion in C# and '#pragma region' in C/C++ +pp_indent_region = 0 # number + +# Whether to indent the code between #region and #endregion +pp_region_indent_code = false # false/true + +# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level +pp_indent_if = 0 # number + +# Control whether to indent the code between #if, #else and #endif when not at file-level +pp_if_indent_code = false # false/true + +# Whether to indent '#define' at the brace level (true) or from column 1 (false) +pp_define_at_level = false # false/true From 36c4d72c5890da9cf3dcdd0df87cad1dd1a5fa4a Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sat, 21 Oct 2017 22:52:15 +0200 Subject: [PATCH 02/10] global: drop vim/emacs indent settings --- src/crypt/certificate.vala | 2 -- src/mconnect/application.vala | 2 -- src/mconnect/battery-proxy.vala | 2 -- src/mconnect/battery.vala | 2 -- src/mconnect/config.vala | 2 -- src/mconnect/core.vala | 2 -- src/mconnect/device-proxy.vala | 2 -- src/mconnect/device.vala | 2 -- src/mconnect/devicechannel.vala | 2 -- src/mconnect/devicemanager-proxy.vala | 2 -- src/mconnect/devicemanager.vala | 2 -- src/mconnect/discovereddevice.vala | 2 -- src/mconnect/discovery.vala | 2 -- src/mconnect/main.vala | 2 -- src/mconnect/mousepad.vala | 2 -- src/mconnect/notification.vala | 2 -- src/mconnect/packet.vala | 2 -- src/mconnect/packethandlerinterface-proxy.vala | 2 -- src/mconnect/packethandlerinterface.vala | 2 -- src/mconnect/packethandlers-proxy.vala | 2 -- src/mconnect/packethandlers.vala | 2 -- src/mconnect/ping-proxy.vala | 2 -- src/mconnect/ping.vala | 2 -- src/mconnect/share-proxy.vala | 2 -- src/mconnect/telephony.vala | 2 -- src/mconnectctl/main.vala | 2 -- 26 files changed, 52 deletions(-) diff --git a/src/crypt/certificate.vala b/src/crypt/certificate.vala index 6521bc7..b7ab52f 100644 --- a/src/crypt/certificate.vala +++ b/src/crypt/certificate.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/application.vala b/src/mconnect/application.vala index effdb51..f14f48f 100644 --- a/src/mconnect/application.vala +++ b/src/mconnect/application.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/battery-proxy.vala b/src/mconnect/battery-proxy.vala index bcf70e6..accf2c6 100644 --- a/src/mconnect/battery-proxy.vala +++ b/src/mconnect/battery-proxy.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/battery.vala b/src/mconnect/battery.vala index 69c13e8..d9baab5 100644 --- a/src/mconnect/battery.vala +++ b/src/mconnect/battery.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/config.vala b/src/mconnect/config.vala index eae32fd..e3e9c5e 100644 --- a/src/mconnect/config.vala +++ b/src/mconnect/config.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/core.vala b/src/mconnect/core.vala index b3bdc53..e448d2b 100644 --- a/src/mconnect/core.vala +++ b/src/mconnect/core.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/device-proxy.vala b/src/mconnect/device-proxy.vala index 1668666..6aa7eb4 100644 --- a/src/mconnect/device-proxy.vala +++ b/src/mconnect/device-proxy.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/device.vala b/src/mconnect/device.vala index 1743058..18e01ef 100644 --- a/src/mconnect/device.vala +++ b/src/mconnect/device.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/devicechannel.vala b/src/mconnect/devicechannel.vala index 6c1f85a..11d2ab6 100644 --- a/src/mconnect/devicechannel.vala +++ b/src/mconnect/devicechannel.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/devicemanager-proxy.vala b/src/mconnect/devicemanager-proxy.vala index 5d0b056..56e0f77 100644 --- a/src/mconnect/devicemanager-proxy.vala +++ b/src/mconnect/devicemanager-proxy.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/devicemanager.vala b/src/mconnect/devicemanager.vala index 6436261..3749c1f 100644 --- a/src/mconnect/devicemanager.vala +++ b/src/mconnect/devicemanager.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/discovereddevice.vala b/src/mconnect/discovereddevice.vala index e795f97..42b289d 100644 --- a/src/mconnect/discovereddevice.vala +++ b/src/mconnect/discovereddevice.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/discovery.vala b/src/mconnect/discovery.vala index d965aa7..67641b4 100644 --- a/src/mconnect/discovery.vala +++ b/src/mconnect/discovery.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/main.vala b/src/mconnect/main.vala index 6a24fd6..bc47d76 100644 --- a/src/mconnect/main.vala +++ b/src/mconnect/main.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/mousepad.vala b/src/mconnect/mousepad.vala index 86e4fa6..62428eb 100644 --- a/src/mconnect/mousepad.vala +++ b/src/mconnect/mousepad.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/notification.vala b/src/mconnect/notification.vala index 76836ce..6fb0f8b 100644 --- a/src/mconnect/notification.vala +++ b/src/mconnect/notification.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/packet.vala b/src/mconnect/packet.vala index e5bb43b..0e1ccdd 100644 --- a/src/mconnect/packet.vala +++ b/src/mconnect/packet.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/packethandlerinterface-proxy.vala b/src/mconnect/packethandlerinterface-proxy.vala index b532209..dabb458 100644 --- a/src/mconnect/packethandlerinterface-proxy.vala +++ b/src/mconnect/packethandlerinterface-proxy.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/packethandlerinterface.vala b/src/mconnect/packethandlerinterface.vala index 98dbdfe..6ade132 100644 --- a/src/mconnect/packethandlerinterface.vala +++ b/src/mconnect/packethandlerinterface.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/packethandlers-proxy.vala b/src/mconnect/packethandlers-proxy.vala index c9af288..48950e6 100644 --- a/src/mconnect/packethandlers-proxy.vala +++ b/src/mconnect/packethandlers-proxy.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/packethandlers.vala b/src/mconnect/packethandlers.vala index 5b8bcbe..9cff4ac 100644 --- a/src/mconnect/packethandlers.vala +++ b/src/mconnect/packethandlers.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/ping-proxy.vala b/src/mconnect/ping-proxy.vala index 26f2c1e..2737d40 100644 --- a/src/mconnect/ping-proxy.vala +++ b/src/mconnect/ping-proxy.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/ping.vala b/src/mconnect/ping.vala index 42b0deb..a7770b9 100644 --- a/src/mconnect/ping.vala +++ b/src/mconnect/ping.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/share-proxy.vala b/src/mconnect/share-proxy.vala index 3d8be82..a278e28 100644 --- a/src/mconnect/share-proxy.vala +++ b/src/mconnect/share-proxy.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnect/telephony.vala b/src/mconnect/telephony.vala index dc862ee..1d20d3e 100644 --- a/src/mconnect/telephony.vala +++ b/src/mconnect/telephony.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/mconnectctl/main.vala b/src/mconnectctl/main.vala index 852613a..ebee13a 100644 --- a/src/mconnectctl/main.vala +++ b/src/mconnectctl/main.vala @@ -1,5 +1,3 @@ -/* ex:ts=4:sw=4:sts=4:et */ -/* -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as From 2684ae393578d999c80dcdd7c63ec2d9038ca31c Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sat, 21 Oct 2017 23:05:07 +0200 Subject: [PATCH 03/10] dir-locals: update emacs indent --- .dir-locals.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.dir-locals.el b/.dir-locals.el index b6b1459..1b22b45 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -1,7 +1,12 @@ ((c-mode . ((c-file-style . "linux") - (indent-tabs-mode . t) + (indent-tabs-mode . nil) (show-trailing-whitespace . t) (c-basic-offset . 4) (tab-width . 4) )) + (vala-mode . ((indent-tabs-mode . nil) + (show-trailing-whitespace . t) + (c-basic-offset . 4) + (tab-width . 4) + )) ) From 4dbf2e9884a63e1301f07fd952d9660ca43f3b9e Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 22 Oct 2017 13:58:38 +0200 Subject: [PATCH 04/10] extra/fmt: helper for vala code formatting --- extra/fmt | 42 ++++++++++++++++++++++++++ uncrustify.cfg => extra/uncrustify.cfg | 0 2 files changed, 42 insertions(+) create mode 100755 extra/fmt rename uncrustify.cfg => extra/uncrustify.cfg (100%) diff --git a/extra/fmt b/extra/fmt new file mode 100755 index 0000000..f2f394b --- /dev/null +++ b/extra/fmt @@ -0,0 +1,42 @@ +#!/bin/sh + +[ "$V" = "1" ] && set -x + +SELFDIR=$(readlink -f $(dirname $0)) +CFG=${SELFDIR}/uncrustify.cfg +UNCRUSTIFY=${UNCRUSTIFY:-uncrustify} +SRCDIR=${SRCDIR:-$(readlink -f ${SELFDIR}/../src ${SELFDIR}/../test | \ + tr '\n' ' ')} + +FILES=$(find $SRCDIR -name '*.vala') +if [ "$FILES" = "" ]; then + echo "no relevant source files found in $SRCDIR" + exit 1 +fi + +cmd=$1 +case "$cmd" in + check) + ${UNCRUSTIFY} -c ${CFG} --check -q $FILES + ;; + apply|fix) + ${UNCRUSTIFY} -c ${CFG} --replace $FILES + ;; + help|-h|--help) + echo "Usage:" + echo " $(basename $0) " + echo + echo "Commands:" + echo " check - check if source code is properly formatted" + echo " exit code will be non-0 if code is badly formatted" + echo " fix - fix formatting" + echo " help - show this message" + echo + echo "Environment variables:" + echo " UNCRUSTIFY - override path to 'uncrustify' tool, default: $UNCRUSTIFY" + echo " SRCDIR - override path to source directory, default: $SRCDIR" + ;; + *) + echo "unsupported command $cmd, see --help" + ;; +esac diff --git a/uncrustify.cfg b/extra/uncrustify.cfg similarity index 100% rename from uncrustify.cfg rename to extra/uncrustify.cfg From 6ce89cb0904c8caa256f75332b6cd556be3b0c7c Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 22 Oct 2017 13:58:53 +0200 Subject: [PATCH 05/10] gitignore: update --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index edf6645..5945c2c 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ *.i*86 *.x86_64 *.hex + +*~ \ No newline at end of file From 152f16b60679c0313cab2914fd68b6476aa1e095 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 22 Oct 2017 19:49:11 +0200 Subject: [PATCH 06/10] travis-build: check code formatting during the build --- extra/travis-build | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/extra/travis-build b/extra/travis-build index 18eced8..6aad1cc 100755 --- a/extra/travis-build +++ b/extra/travis-build @@ -39,7 +39,8 @@ deps_fedora() { at-spi2-core-devel \ gtk3-devel \ glib-networking \ - tree + tree \ + uncrustify } deps_opensuse() { @@ -57,7 +58,8 @@ deps_opensuse() { at-spi2-core-devel \ gtk3-devel \ glib-networking \ - tree + tree \ + uncrustify } deps_archlinux() { @@ -76,7 +78,8 @@ deps_archlinux() { gtk3 \ gnutls \ glib-networking \ - tree + tree \ + uncrustify } deps_ubuntu_xenial() { @@ -92,7 +95,8 @@ deps_ubuntu_xenial() { libnotify-dev \ libgtk-3-dev \ glib-networking \ - tree + tree \ + uncrustify } install_deps() { @@ -117,7 +121,8 @@ install_deps() { build() { set -ex - mkdir build && \ + ./extra/fmt check && \ + mkdir build && \ cd build && \ meson .. && \ ninja && \ From 457a025ef8bfb00026ff95ac039546b165caf09e Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 22 Oct 2017 20:06:59 +0200 Subject: [PATCH 07/10] travis-build: make sure to exit with failure if one of the build steps fails --- extra/travis-build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extra/travis-build b/extra/travis-build index 6aad1cc..e2fa423 100755 --- a/extra/travis-build +++ b/extra/travis-build @@ -126,7 +126,8 @@ build() { cd build && \ meson .. && \ ninja && \ - ninja test + ninja test \ + || false DESTDIR=$PWD/install-dir ninja install (cd install-dir; LC_ALL=C tree -pan . > ../current-tree) From f3a5cfe0abbe648435e86883587eb812dfe72bf9 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 22 Oct 2017 20:08:54 +0200 Subject: [PATCH 08/10] travis-build: do not raise an error if build directory exists Useful when doing local builds --- extra/travis-build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/travis-build b/extra/travis-build index e2fa423..793dc22 100755 --- a/extra/travis-build +++ b/extra/travis-build @@ -122,7 +122,7 @@ install_deps() { build() { set -ex ./extra/fmt check && \ - mkdir build && \ + mkdir -p build && \ cd build && \ meson .. && \ ninja && \ From c6bcb097f1b3e269a151eaafc9382ba6fad9b918 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 22 Oct 2017 21:25:01 +0200 Subject: [PATCH 09/10] extra/fmt: log uncrustify version when running checks --- extra/fmt | 1 + 1 file changed, 1 insertion(+) diff --git a/extra/fmt b/extra/fmt index f2f394b..ce05271 100755 --- a/extra/fmt +++ b/extra/fmt @@ -17,6 +17,7 @@ fi cmd=$1 case "$cmd" in check) + echo "-- uncrustify version $(${UNCRUSTIFY} --version)" ${UNCRUSTIFY} -c ${CFG} --check -q $FILES ;; apply|fix) From 90cd6c894bc18873a350559422ef38fdba2b57e9 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Sun, 22 Oct 2017 21:25:57 +0200 Subject: [PATCH 10/10] travis-build: allow suppressing of formatter errors on selected distros Some distributions, notably Ubuntu 16.04 and OpenSUSE Tumbleweed (as of 22.10.17) ship an older version of uncrustify. This version may report formatting errors. --- extra/travis-build | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/extra/travis-build b/extra/travis-build index 793dc22..1578b19 100755 --- a/extra/travis-build +++ b/extra/travis-build @@ -121,8 +121,12 @@ install_deps() { build() { set -ex - ./extra/fmt check && \ - mkdir -p build && \ + ./extra/fmt check || { + echo "WARNING: code formatting check failed" + [ -z "${SUPPRESS_FMT}" ] && false + } + + mkdir -p build && \ cd build && \ meson .. && \ ninja && \ @@ -137,6 +141,14 @@ build() { build_in_container() { install_deps $1 + # distro specific quirks + case "$1" in + ubuntu-xenial|opensuse) + echo "$1 is using an outdated version of uncrustify, suppress formatting errors" + export SUPPRESS_FMT=1 + ;; + esac + build }