summaryrefslogtreecommitdiff
path: root/lib/sway/ipc.vala
blob: d0c219d33cbc9258394892943e7b483ce88eb5f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
namespace AstalSway {
private const string IPC_MAGIC = "i3-ipc";

private struct IpcReponse {
    public PayloadType type;
    public string payload;
}

// Basic interface to send and receive data through Sway IPjC
private class Ipc : Object {
    private string SWAYSOCK = GLib.Environment.get_variable("SWAYSOCK");

    internal void init() throws Error {
        SWAYSOCK = GLib.Environment.get_variable("SWAYSOCK");
        
        if (SWAYSOCK == null) {
            critical("Unable to detect Sway");
            return;
        }
    }
    
    internal SocketConnection? connection() {
        try {
                SocketConnection socket = new SocketClient().connect(new UnixSocketAddress(SWAYSOCK), null);
                return socket;
        } catch (Error err) {
                critical(err.message);
                return null;
        }
    }

    internal void send(OutputStream stream, PayloadType type, string payload) {
        Array<uint8> message = new Array<uint8> ();

        uint8[] magic_str = IPC_MAGIC.data;
        uint32 pl_length = (uint32) payload.length; 
        uint32 pl_type = (uint32) type;
        uint8[] pl_data = payload.data;

        message.append_vals(magic_str, magic_str.length);
        message.append_vals((uint8 *)&pl_length, 4);
        message.append_vals((uint8 *)&pl_type, 4);
        message.append_vals(pl_data, pl_data.length);
        
        stream.write(message.data);
    }

    internal IpcReponse? receive(InputStream stream) {
        var header = stream.read_bytes(14);
            uint8 data[14] = header.get_data();
            if (data == null) {
                    return null;
            }
            uint32 pl_length = *(uint32 *)&data[IPC_MAGIC.length];
            PayloadType pl_type = *(uint32 *)&data[IPC_MAGIC.length+4];
             
            var payload = stream.read_bytes(pl_length);
            
            var result = payload.get_data();
            result += '\0';
            
            return {pl_type, (string)result};

    }

    internal async IpcReponse? receive_async(InputStream stream) {
        var header = yield stream.read_bytes_async(14, Priority.DEFAULT, null);
            uint8 data[14] = header.get_data();
            if (data == null) {
                    return null;
            }
            uint32 pl_length = *(uint32 *)&data[IPC_MAGIC.length];
            PayloadType pl_type = *(uint32 *)&data[IPC_MAGIC.length+4];
             
            var payload = yield stream.read_bytes_async(pl_length, Priority.DEFAULT, null);
            
            var result = payload.get_data();
            result += '\0';

            return {pl_type, (string)result};
    }

    public string message(PayloadType type, string payload) {
        SocketConnection conn = connection();
        if (conn == null) {
            return "";
        }
        
        send(conn.output_stream, type, payload);
        var result = receive(conn.input_stream);
        conn.close(null);
     
        return result.payload;
    }
    
    public async string message_async(PayloadType type, string payload) {
        SocketConnection conn = connection();
        if (conn == null) {
            return "";
        }
        
        send(conn.output_stream, type, payload);
        var result = yield receive_async(conn.input_stream);
        conn.close(null);
     
        return result.payload;
    }
}
}