Skip to content
Snippets Groups Projects
Select Git revision
  • b986e764bb413f11fcee0e9fa3de4ea259a28420
  • master default
2 results

Packet.vala

Blame
  • Packet.vala 6.48 KiB
    /**
     * 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 <maciek.borzecki (at] gmail.com>
     * gyan000 <gyan000 (at] ijaz.fr>
     */
    
    using Json;
    
    public errordomain PacketError {
        MALFORMED
    }
    
    namespace MConnect {
    
        public class Packet : GLib.Object {
    
            public const int PROTOCOL_VERSION = 7;
            public const string IDENTITY = "kdeconnect.identity";
            public const string PAIR = "kdeconnect.pair";
            public const string ENCRYPTED = "kdeconnect.encrypted";
    
            /**
             * Payload:
             * Wrapper for payload transfer information
             */
            public struct Payload {
                public uint64 size;
                public uint port;
            }
            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 Packet.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");
    
                    debug ("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 (bool pretty_format = false) {
                var gen = new Json.Generator ();
                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 (pretty_format);
                return gen.to_data (null);;
            }
        }
    }