feat: recieve file descriptors
Feels super hacky, but I'm not sure there is a better way to handle it. The crux of the problem is that wayland does not seem to make any guarantees about the location of file descriptors.dev
parent
7a9e12abf8
commit
a7128eaf34
|
@ -128,7 +128,7 @@ pub fn main() !void {
|
||||||
std.debug.print("<- wl_seat.name = {s}\n", .{name.name});
|
std.debug.print("<- wl_seat.name = {s}\n", .{name.name});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (header.object_id == 1) {
|
} else if (header.object_id == DISPLAY_ID) {
|
||||||
const event = try wayland.deserialize(wayland.core.Display.Event, header, body);
|
const event = try wayland.deserialize(wayland.core.Display.Event, header, body);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.@"error" => |err| std.debug.print("<- error({}): {} {s}\n", .{ err.object_id, err.code, err.message }),
|
.@"error" => |err| std.debug.print("<- error({}): {} {s}\n", .{ err.object_id, err.code, err.message }),
|
||||||
|
@ -304,12 +304,19 @@ pub fn main() !void {
|
||||||
} else if (header.object_id == wl_keyboard_id) {
|
} else if (header.object_id == wl_keyboard_id) {
|
||||||
const event = try wayland.deserialize(wayland.core.Keyboard.Event, header, body);
|
const event = try wayland.deserialize(wayland.core.Keyboard.Event, header, body);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
// .keymap => |keymap| {},
|
.keymap => |keymap| {
|
||||||
|
const fd = conn.fd_queue.orderedRemove(0);
|
||||||
|
std.debug.print("keymap format={}, size={}, fd={}\n", .{
|
||||||
|
keymap.format,
|
||||||
|
keymap.size,
|
||||||
|
fd,
|
||||||
|
});
|
||||||
|
},
|
||||||
else => {
|
else => {
|
||||||
std.debug.print("<- wl_keyboard@{}\n", .{event});
|
std.debug.print("<- wl_keyboard@{}\n", .{event});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (header.object_id == 1) {
|
} else if (header.object_id == DISPLAY_ID) {
|
||||||
const event = try wayland.deserialize(wayland.core.Display.Event, header, body);
|
const event = try wayland.deserialize(wayland.core.Display.Event, header, body);
|
||||||
switch (event) {
|
switch (event) {
|
||||||
.@"error" => |err| std.debug.print("<- error({}): {} {s}\n", .{ err.object_id, err.code, err.message }),
|
.@"error" => |err| std.debug.print("<- error({}): {} {s}\n", .{ err.object_id, err.code, err.message }),
|
||||||
|
|
64
src/main.zig
64
src/main.zig
|
@ -113,7 +113,7 @@ pub fn deserializeArguments(comptime Signature: type, buffer: []const u32) !Sign
|
||||||
var result: Signature = undefined;
|
var result: Signature = undefined;
|
||||||
var pos: usize = 0;
|
var pos: usize = 0;
|
||||||
inline for (std.meta.fields(Signature)) |field| {
|
inline for (std.meta.fields(Signature)) |field| {
|
||||||
if (field.type == types.Fd) continue; // Must be handled
|
if (field.type == types.Fd) continue;
|
||||||
switch (@typeInfo(field.type)) {
|
switch (@typeInfo(field.type)) {
|
||||||
.Int => |int_info| switch (int_info.signedness) {
|
.Int => |int_info| switch (int_info.signedness) {
|
||||||
.signed => @field(result, field.name) = try readInt(buffer, &pos),
|
.signed => @field(result, field.name) = try readInt(buffer, &pos),
|
||||||
|
@ -458,6 +458,7 @@ pub const Conn = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
send_buffer: []u32,
|
send_buffer: []u32,
|
||||||
recv_buffer: []u32,
|
recv_buffer: []u32,
|
||||||
|
fd_queue: std.ArrayListUnmanaged(std.os.fd_t),
|
||||||
socket: std.net.Stream,
|
socket: std.net.Stream,
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator, display_path: []const u8) !Conn {
|
pub fn init(alloc: std.mem.Allocator, display_path: []const u8) !Conn {
|
||||||
|
@ -467,6 +468,7 @@ pub const Conn = struct {
|
||||||
.allocator = alloc,
|
.allocator = alloc,
|
||||||
.send_buffer = send_buffer,
|
.send_buffer = send_buffer,
|
||||||
.recv_buffer = recv_buffer,
|
.recv_buffer = recv_buffer,
|
||||||
|
.fd_queue = .{},
|
||||||
.socket = try std.net.connectUnixSocket(display_path),
|
.socket = try std.net.connectUnixSocket(display_path),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -474,6 +476,7 @@ pub const Conn = struct {
|
||||||
pub fn deinit(conn: *Conn) void {
|
pub fn deinit(conn: *Conn) void {
|
||||||
conn.allocator.free(conn.send_buffer);
|
conn.allocator.free(conn.send_buffer);
|
||||||
conn.allocator.free(conn.recv_buffer);
|
conn.allocator.free(conn.recv_buffer);
|
||||||
|
conn.fd_queue.deinit(conn.allocator);
|
||||||
conn.socket.close();
|
conn.socket.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,21 +529,58 @@ pub const Conn = struct {
|
||||||
|
|
||||||
pub const Message = struct { Header, []const u32 };
|
pub const Message = struct { Header, []const u32 };
|
||||||
pub fn recv(conn: *Conn) !Message {
|
pub fn recv(conn: *Conn) !Message {
|
||||||
// TODO: recvmesg and read fds
|
// TODO: make this less messy
|
||||||
|
// Read header
|
||||||
|
@memset(conn.recv_buffer, 0);
|
||||||
|
var iov: [1]std.os.iovec = .{.{
|
||||||
|
.iov_base = std.mem.sliceAsBytes(conn.recv_buffer).ptr,
|
||||||
|
.iov_len = @sizeOf(Header),
|
||||||
|
}};
|
||||||
|
var control_msg: cmsg(std.os.fd_t) = undefined;
|
||||||
|
const control_bytes = std.mem.asBytes(&control_msg);
|
||||||
|
var socket_msg = std.os.msghdr{
|
||||||
|
.name = null,
|
||||||
|
.namelen = 0,
|
||||||
|
.iov = &iov,
|
||||||
|
.iovlen = iov.len,
|
||||||
|
.control = control_bytes.ptr,
|
||||||
|
.controllen = @intCast(control_bytes.len),
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const size = std.os.linux.recvmsg(conn.socket.handle, &socket_msg, 0);
|
||||||
|
|
||||||
|
if (size < @sizeOf(Header)) return error.SocketClosed;
|
||||||
|
|
||||||
var header: Header = undefined;
|
var header: Header = undefined;
|
||||||
const header_bytes_read = try conn.socket.readAll(std.mem.asBytes(&header));
|
@memcpy(std.mem.asBytes(&header), iov[0].iov_base[0..@sizeOf(Header)]);
|
||||||
if (header_bytes_read < @sizeOf(Header)) {
|
|
||||||
return error.SocketClosed;
|
if (socket_msg.controllen != 0) {
|
||||||
|
try conn.fd_queue.append(conn.allocator, control_msg.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const msg_size = (header.size_and_opcode.size - @sizeOf(Header)) / @sizeOf(u32);
|
// Read body
|
||||||
if (msg_size > conn.recv_buffer.len) {
|
const body_size = (header.size_and_opcode.size - @sizeOf(Header)) / @sizeOf(u32);
|
||||||
var new_size = conn.recv_buffer.len * 2;
|
|
||||||
while (new_size < msg_size) new_size *= 2;
|
iov[0] = .{
|
||||||
conn.recv_buffer = try conn.allocator.realloc(conn.recv_buffer, new_size);
|
.iov_base = std.mem.sliceAsBytes(conn.recv_buffer).ptr,
|
||||||
|
.iov_len = body_size * @sizeOf(u32),
|
||||||
|
};
|
||||||
|
socket_msg = std.os.msghdr{
|
||||||
|
.name = null,
|
||||||
|
.namelen = 0,
|
||||||
|
.iov = &iov,
|
||||||
|
.iovlen = iov.len,
|
||||||
|
.control = control_bytes.ptr,
|
||||||
|
.controllen = @intCast(control_bytes.len),
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
const size2 = std.os.linux.recvmsg(conn.socket.handle, &socket_msg, 0);
|
||||||
|
const message = conn.recv_buffer[0 .. size2 / @sizeOf(u32)];
|
||||||
|
|
||||||
|
if (socket_msg.controllen != 0) {
|
||||||
|
try conn.fd_queue.append(conn.allocator, control_msg.data);
|
||||||
}
|
}
|
||||||
const bytes_read = try conn.socket.readAll(std.mem.sliceAsBytes(conn.recv_buffer[0..msg_size]));
|
|
||||||
const message = conn.recv_buffer[0 .. bytes_read / @sizeOf(u32)];
|
|
||||||
|
|
||||||
return .{ header, message };
|
return .{ header, message };
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue