diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..c06d6d6 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,14 @@ +bin_PROGRAMS = mconnect + +mconnect_SOURCES = src/main.vala \ + src/discovery.vala \ + src/packet.vala \ + src/device.vala \ + src/devicemanager.vala + +mconnect_LDADD = $(MCONNECT_LIBS) + +mconnect_CFLAGS = $(MCONNECT_CFLAGS) + +VALAFLAGS = $(MCONNECT_VALAFLAGS) + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..8c81eaa --- /dev/null +++ b/configure.ac @@ -0,0 +1,56 @@ +# +# 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# AUTHORS +# Maciek Borzecki +# +AC_PREREQ(2.61) +AC_INIT([mconnect], [0.1.0], [maciek.borzecki@gmail.com]) +AC_CONFIG_SRCDIR([src/main.vala]) +AC_CONFIG_AUX_DIR([.]) +AC_PROG_MAKE_SET +AM_INIT_AUTOMAKE([tar-pax foreign subdir-objects]) +AM_SILENT_RULES([yes]) + +AM_MAINTAINER_MODE + +# Checks for header files. +# AC_HEADER_STDC +# AC_CHECK_HEADERS([stdlib.h]) + +# Checks for typedefs, structures, and compiler characteristics. +# AC_C_CONST + +# Checks for programs. +AC_PROG_CC +AM_PROG_VALAC([0.7.0]) +AC_PROG_INSTALL + +AC_SUBST(MCONNECT_VALAFLAGS, ["--pkg=json-glib-1.0 --pkg=gee-0.8"]) +# AC_SUBST(MCONNECT_VALAFLAGS, [--pkg=json-glib-1.0 --pkg=gee-0.8]) +PKG_CHECK_MODULES(MCONNECT, [glib-2.0, + gobject-2.0, + gio-2.0, + gio-unix-2.0, + json-glib-1.0, + gee-0.8 + ]) +AC_SUBST(MCONNECT_CFLAGS) +AC_SUBST(MCONNECT_LIBS) + +# Files to generate +AC_CONFIG_FILES([Makefile]) + +# Output +AC_OUTPUT diff --git a/src/device.vala b/src/device.vala new file mode 100644 index 0000000..2ce6586 --- /dev/null +++ b/src/device.vala @@ -0,0 +1,59 @@ +/* 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * AUTHORS + * Maciek Borzecki + */ + +class Device : 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; } + public bool paired { get; set; default = false; } + + public Device() { + + } + + public Device.from_identity(Packet pkt, InetAddress host) { + 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"); + + debug("added new device: %s", this.to_string()); + } + + ~Device() { + + } + + public string to_unique_string() { + return ""; + } + + public string to_string() { + return "%s-%s-%s-%u".printf(this.device_id, this.device_name, + this.device_type, this.protocol_version); + } + +} \ No newline at end of file diff --git a/src/devicemanager.vala b/src/devicemanager.vala new file mode 100644 index 0000000..45ee5ce --- /dev/null +++ b/src/devicemanager.vala @@ -0,0 +1,34 @@ +/* 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * AUTHORS + * Maciek Borzecki + */ +using Gee; + +class DeviceManager : GLib.Object +{ + private HashMap devices; + + public DeviceManager() { + debug("device manager.."); + } + + public void found_device(Device dev) { + debug("new device: %s", dev.to_string()); + } + +} \ No newline at end of file diff --git a/src/discovery.vala b/src/discovery.vala new file mode 100644 index 0000000..c6f4dcb --- /dev/null +++ b/src/discovery.vala @@ -0,0 +1,101 @@ +/* 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * AUTHORS + * Maciek Borzecki + */ + +class Discovery : GLib.Object +{ + private Socket socket = null; + + public signal void device_found(Device dev); + + public Discovery() { + } + + ~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); + + 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()); + } + + private void incomingPacket() { + debug("incoming packet"); + + uint8 buffer[4096]; + SocketAddress sa; + InetSocketAddress isa; + + + try { + ssize_t read = this.socket.receive_from(out sa, buffer); + isa = (InetSocketAddress)sa; + message("got %zd bytes from: %s:%u", read, + isa.address.to_string(), isa.port); + } catch (Error e) { + message("faile to receive packet: %s", e.message); + return; + } + + message("message data: %s", (string)buffer); + + 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; + } + + var dev = new Device.from_identity(pkt, host); + debug("connection from device: \'%s\', responds at: %s:%u", + dev.device_name, host.to_string(), dev.tcp_port); + + device_found(dev); + } +} diff --git a/src/main.vala b/src/main.vala new file mode 100644 index 0000000..a7a9ccf --- /dev/null +++ b/src/main.vala @@ -0,0 +1,39 @@ +/* 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * AUTHORS + * Maciek Borzecki + */ + +public static int main(string[] args) +{ + var loop = new MainLoop(); + var discovery = new Discovery(); + var manager = new DeviceManager(); + + discovery.device_found.connect((disc, dev) => { + manager.found_device(dev); + }); + + try { + discovery.listen(); + } catch (Error e) { + message("failed to setup device listener: %s", e.message); + return 1; + } + loop.run(); + return 0; +} \ No newline at end of file diff --git a/src/packet.vala b/src/packet.vala new file mode 100644 index 0000000..0f154d6 --- /dev/null +++ b/src/packet.vala @@ -0,0 +1,58 @@ +/* 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * AUTHORS + * Maciek Borzecki + */ + +using Json; + +class Packet : GLib.Object { + public const string IDENTITY = "kdeconnect.identity"; + public const string PAIR = "kdeconnect.pair"; + public const string ENCRYPT = "kdeconnect.encrypt"; + + public string pkt_type { get; private set; default = ""; } + public Json.Object body { get; private set; default = null; } + + private Packet(string type, Json.Object body) { + this.pkt_type = type; + this.body = body; + } + + public static Packet? new_from_data(string data) { + var jp = new Json.Parser(); + + try { + jp.load_from_data(data, -1); + var root_obj = jp.get_root().get_object(); + var type = root_obj.get_string_member("type"); + debug("packet type: %s", type); + var body = root_obj.get_object_member("body"); + // var device_name = body.get_string_member("deviceName"); + // var port = (uint) body.get_int_member("tcpPort"); + return new Packet(type, body); + } catch (Error e) { + message("failed to parse message: \'%s\', error: %s", + data, e.message); + } + return null; + } + + public string decrypt() { + return ""; + } +} \ No newline at end of file