feat: transparently send fds
parent
ea4a75cc76
commit
7a9e12abf8
|
@ -196,41 +196,16 @@ pub fn main() !void {
|
|||
|
||||
const wl_shm_pool_id = id_pool.create();
|
||||
{
|
||||
var buffer: [10]u32 = undefined;
|
||||
const message = try wayland.serialize(
|
||||
std.debug.print("framebuffer_fd: {}\n", .{framebuffer_fd});
|
||||
try conn.send(
|
||||
wayland.core.Shm.Request,
|
||||
&buffer,
|
||||
shm_id,
|
||||
.{ .create_pool = .{
|
||||
.new_id = wl_shm_pool_id,
|
||||
.fd = @enumFromInt(framebuffer_fd),
|
||||
.size = framebuffer_file_len,
|
||||
} },
|
||||
);
|
||||
// Send the file descriptor through a control message
|
||||
const message_bytes = std.mem.sliceAsBytes(message);
|
||||
const msg_iov = [_]std.os.iovec_const{
|
||||
.{
|
||||
.iov_base = message_bytes.ptr,
|
||||
.iov_len = message_bytes.len,
|
||||
},
|
||||
};
|
||||
const control_message = cmsg(std.os.fd_t){
|
||||
.level = std.os.SOL.SOCKET,
|
||||
.type = 0x01, // value of SCM_RIGHTS
|
||||
.data = framebuffer_fd,
|
||||
};
|
||||
const socket_message = std.os.msghdr_const{
|
||||
.name = null,
|
||||
.namelen = 0,
|
||||
.iov = &msg_iov,
|
||||
.iovlen = msg_iov.len,
|
||||
// .control = null,
|
||||
// .controllen = 0,
|
||||
.control = &control_message,
|
||||
.controllen = @sizeOf(cmsg(std.os.fd_t)),
|
||||
.flags = 0,
|
||||
};
|
||||
_ = try std.os.sendmsg(conn.socket.handle, &socket_message, 0);
|
||||
}
|
||||
|
||||
const wl_buffer_id = id_pool.create();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const types = @import("types.zig");
|
||||
|
||||
pub const Display = struct {
|
||||
pub const Request = union(enum) {
|
||||
sync: struct {
|
||||
|
@ -90,7 +92,7 @@ pub const Shm = struct {
|
|||
create_pool: struct {
|
||||
new_id: u32,
|
||||
// file descriptors are sent through a control message
|
||||
// fd: u32,
|
||||
fd: types.Fd,
|
||||
size: u32,
|
||||
},
|
||||
};
|
||||
|
@ -306,7 +308,7 @@ pub const Keyboard = struct {
|
|||
pub const Event = union(enum) {
|
||||
keymap: struct {
|
||||
format: KeymapFormat,
|
||||
// fd: u32,
|
||||
fd: types.Fd,
|
||||
size: u32,
|
||||
},
|
||||
enter: struct {
|
||||
|
|
69
src/main.zig
69
src/main.zig
|
@ -3,6 +3,7 @@ const testing = std.testing;
|
|||
pub const core = @import("./core.zig");
|
||||
pub const xdg = @import("./xdg.zig");
|
||||
pub const zxdg = @import("./zxdg.zig");
|
||||
pub const types = @import("./types.zig");
|
||||
|
||||
pub fn getDisplayPath(gpa: std.mem.Allocator) ![]u8 {
|
||||
const xdg_runtime_dir_path = try std.process.getEnvVarOwned(gpa, "XDG_RUNTIME_DIR");
|
||||
|
@ -112,6 +113,7 @@ pub fn deserializeArguments(comptime Signature: type, buffer: []const u32) !Sign
|
|||
var result: Signature = undefined;
|
||||
var pos: usize = 0;
|
||||
inline for (std.meta.fields(Signature)) |field| {
|
||||
if (field.type == types.Fd) continue; // Must be handled
|
||||
switch (@typeInfo(field.type)) {
|
||||
.Int => |int_info| switch (int_info.signedness) {
|
||||
.signed => @field(result, field.name) = try readInt(buffer, &pos),
|
||||
|
@ -169,11 +171,36 @@ pub fn calculateSerializedWordLen(comptime Signature: type, message: Signature)
|
|||
return pos;
|
||||
}
|
||||
|
||||
pub fn countFds(comptime Signature: type) usize {
|
||||
if (Signature == void) return 0;
|
||||
var count: usize = 0;
|
||||
inline for (std.meta.fields(Signature)) |field| {
|
||||
if (field.type == types.Fd) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn extractFds(comptime Signature: type, message: *const Signature) [countFds(Signature)]*const types.Fd {
|
||||
if (Signature == void) return [_]*const types.Fd{};
|
||||
var fds: [countFds(Signature)]*const types.Fd = undefined;
|
||||
var i: usize = 0;
|
||||
inline for (std.meta.fields(Signature)) |field| {
|
||||
if (field.type == types.Fd) {
|
||||
fds[i] = &@field(message, field.name);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
return fds;
|
||||
}
|
||||
|
||||
/// Message must live until the iovec array is written.
|
||||
pub fn serializeArguments(comptime Signature: type, buffer: []u32, message: Signature) ![]u32 {
|
||||
if (Signature == void) return buffer[0..0];
|
||||
var pos: usize = 0;
|
||||
inline for (std.meta.fields(Signature)) |field| {
|
||||
if (field.type == types.Fd) continue;
|
||||
switch (@typeInfo(field.type)) {
|
||||
.Int => {
|
||||
if (pos >= buffer.len) return error.OutOfMemory;
|
||||
|
@ -416,6 +443,17 @@ pub fn registerGlobals(alloc: std.mem.Allocator, id_pool: *IdPool, socket: std.n
|
|||
return ids;
|
||||
}
|
||||
|
||||
fn cmsg(comptime T: type) type {
|
||||
const padding_size = (@sizeOf(T) + @sizeOf(c_long) - 1) & ~(@as(usize, @sizeOf(c_long)) - 1);
|
||||
return extern struct {
|
||||
len: c_ulong = @sizeOf(@This()) - padding_size,
|
||||
level: c_int,
|
||||
type: c_int,
|
||||
data: T,
|
||||
_padding: [padding_size]u8 align(1) = [_]u8{0} ** padding_size,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Conn = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
send_buffer: []u32,
|
||||
|
@ -455,11 +493,40 @@ pub const Conn = struct {
|
|||
|
||||
break msg;
|
||||
};
|
||||
try conn.socket.writeAll(std.mem.sliceAsBytes(msg));
|
||||
const msg_bytes = std.mem.sliceAsBytes(msg);
|
||||
const msg_iov = [_]std.os.iovec_const{
|
||||
.{
|
||||
.iov_base = msg_bytes.ptr,
|
||||
.iov_len = msg_bytes.len,
|
||||
},
|
||||
};
|
||||
const fds = switch (message) {
|
||||
inline else => |*payload| extractFds(@TypeOf(payload.*), payload),
|
||||
};
|
||||
var ctrl_msgs: [fds.len]cmsg(std.os.fd_t) = undefined;
|
||||
for (fds, 0..) |fdp, i| {
|
||||
std.debug.print("fd {}: {}\n", .{ i, fdp.* });
|
||||
ctrl_msgs[i] = .{
|
||||
.level = std.os.SOL.SOCKET,
|
||||
.type = 0x01,
|
||||
.data = @intFromEnum(fdp.*),
|
||||
};
|
||||
}
|
||||
const socket_msg = std.os.msghdr_const{
|
||||
.name = null,
|
||||
.namelen = 0,
|
||||
.iov = &msg_iov,
|
||||
.iovlen = msg_iov.len,
|
||||
.control = &ctrl_msgs,
|
||||
.controllen = @intCast(@sizeOf(cmsg(std.os.fd_t)) * ctrl_msgs.len),
|
||||
.flags = 0,
|
||||
};
|
||||
_ = try std.os.sendmsg(conn.socket.handle, &socket_msg, 0);
|
||||
}
|
||||
|
||||
pub const Message = struct { Header, []const u32 };
|
||||
pub fn recv(conn: *Conn) !Message {
|
||||
// TODO: recvmesg and read fds
|
||||
var header: Header = undefined;
|
||||
const header_bytes_read = try conn.socket.readAll(std.mem.asBytes(&header));
|
||||
if (header_bytes_read < @sizeOf(Header)) {
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
const std = @import("std");
|
||||
pub const Fd = enum(std.os.fd_t) { _ };
|
Loading…
Reference in New Issue