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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
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() throws Error {
return new SocketClient().connect(new UnixSocketAddress(SWAYSOCK), null);
}
internal void send(OutputStream stream, PayloadType type, string payload) throws Error {
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) {
try {
var header = stream.read_bytes(14);
uint8 data[14] = header.get_data();
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};
} catch (Error err) {
critical("could not receive message: %s", err.message);
return null;
}
}
internal async IpcReponse? receive_async(InputStream stream) {
try {
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};
} catch (Error err) {
critical("could not receive message: %s", err.message);
return null;
}
}
public string message(PayloadType type, string payload) {
try {
SocketConnection conn = connection();
if (conn == null) {
return "";
}
send(conn.output_stream, type, payload);
var result = receive(conn.input_stream);
conn.close(null);
if (result == null) {
return "";
}
return result.payload;
} catch (Error err) {
critical("message failed: %s", err.message);
return "";
}
}
public async string message_async(PayloadType type, string payload) {
try {
SocketConnection conn = connection();
if (conn == null) {
return "";
}
send(conn.output_stream, type, payload);
var result = yield receive_async(conn.input_stream);
conn.close(null);
if (result == null) {
return "";
}
return result.payload;
} catch (Error err) {
critical("message failed: %s", err.message);
return "";
}
}
}
}
|