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
128
129
130
|
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();
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};
} 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 "";
}
}
}
}
|